[TOC]
1. 概念
Spring AOP提供的@Before
、@After
、@AfterReturning
、@AfterThrowing
、Around
只对类的现有方法进行增强处理。如果需要对现有类增加新的方法,有两种方法可实现:
- 扩展现有类:实现简单,但如果对多个现有类进行扩展时,需增加多个类
- 使用
@DeclareParents
注解实现:实现复杂,可使用通配符匹配
本文介绍@DeclareParents
注解实现的增强。
2. 通过@DeclareParents
注解实现
2.1 maven依赖
<!--spring的context上下文即IoC容器-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring aop依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!--spring测试依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!--junit依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--spring aop依赖AspectJ-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
2.2 实现
- 待增强功能
package com.cui.springShizhan.ch4.DeclareParents;
public interface IWaitingProxy {
public void method();
}
package com.cui.springShizhan.ch4.DeclareParents;
import org.springframework.stereotype.Component;
@Component
public class WaitingProxyImpl implements IWaitingProxy {
@Override
public void method() {
System.out.println("现有方法");
}
}
- 代理类
package com.cui.springShizhan.ch4.DeclareParents;
public interface IDeclareParentProxy {
public void declareParentProxy();
}
package com.cui.springShizhan.ch4.DeclareParents;
import org.springframework.stereotype.Component;
@Component
public class DeclareParentProxyImpl implements IDeclareParentProxy{
@Override
public void declareParentProxy() {
System.out.println("我是增强代理方法");
}
}
- 切面配置
package com.cui.springShizhan.ch4.DeclareParents;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AspectJIntroductionAnnotationAdvice {
@DeclareParents(value = "com.cui.springShizhan.ch4.DeclareParents.*", defaultImpl = DeclareParentProxyImpl.class)
private IDeclareParentProxy iDeclareParentProxy;
}
说明:
- value:相当于XML中的types-matching,待引入增强作用的类的表达式, 支持通配符
- defaultImpl:引入增强的具体实现
- spring配置
package com.cui.springShizhan.ch4.DeclareParents;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("com.cui.springShizhan.ch4")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
}
- 单元测试
package springshizhan.ch4;
import com.cui.springShizhan.ch4.DeclareParents.AppConfig;
import com.cui.springShizhan.ch4.DeclareParents.IDeclareParentProxy;
import com.cui.springShizhan.ch4.DeclareParents.IWaitingProxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class DeclareParentsAnnotationTest {
@Resource
private IWaitingProxy iWaitingProxy;
@Test
public void test() {
iWaitingProxy.method();
IDeclareParentProxy iDeclareParentProxy = (IDeclareParentProxy) iWaitingProxy;
iDeclareParentProxy.declareParentProxy();
}
}
/*结果
现有方法
我是增强代理方法
*/
3. 通过XML配置实现
主要区别为配置文件:
方式1:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="iWaitingProxy" class="com.cui.springShizhan.ch4.DeclareParents.WaitingProxyImpl"/>
<bean id="iDeclareParentProxy" class="com.cui.springShizhan.ch4.DeclareParents.DeclareParentProxyImpl"/>
<aop:config proxy-target-class="true">
<aop:aspect>
<aop:declare-parents
types-matching="com.cui.springShizhan.ch4..*"
implement-interface="com.cui.springShizhan.ch4.DeclareParents.IDeclareParentProxy"
delegate-ref="iDeclareParentProxy"/>
</aop:aspect>
</aop:config>
</beans>
方式2:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="iWaitingProxy" class="com.cui.springShizhan.ch4.DeclareParents.WaitingProxyImpl"/>
<aop:config proxy-target-class="true">
<aop:aspect>
<aop:declare-parents
types-matching="com.cui.springShizhan.ch4..*"
implement-interface="com.cui.springShizhan.ch4.DeclareParents.IDeclareParentProxy"
default-impl="com.cui.springShizhan.ch4.DeclareParents.DeclareParentProxyImpl"/>
</aop:aspect>
</aop:config>
</beans>
属性解释:
- types-matching:待增强类的表达式,支持通配符
- implement-interface:引入增强的方法所在的接口
- delegate-ref:引入增强的实现bean的id(方式1)
- default-impl:引入增强的实现类的全路径名称(方式2,使用该方式,无需把增强类的
Bean
注入到Spring容器中)
注:delegate-ref
和default-impl
仍选一个实现即可
4. 参考
- Spring源码-AOP(八)-引入增强
- spring-AOP通过注解@DeclareParents引入新的方法
- 《Spring 实战》第4版
网友评论