1、在spring专栏里面我仔细的分析了在spring中是如何使用SpringAOP的,以及SpringAOP的核心原理,那么我们来会回忆一下,在spring中是如何使用SpringAOP的:
方式1:基于code,使用ProxyFactory或者AspectJProxyFactory
Ⅰ、ProxyFactory
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
BeforeAdvice beforeAdvice = new UserServiceRegistryBeforeAdvice();
AfterReturningAdvice afterReturningAdvice = new UserviceRegistryAfetrReturnAdvice();
ProxyFactory proxyFactory = new ProxyFactory();
/*
可添加多个增强,形成增强链,调用顺序跟添加顺序一致,
也可以使用proxyFactory.addAdvice(1, beforeAdvice);来指定位置。
*/
proxyFactory.addAdvice(1, beforeAdvice);
proxyFactory.addAdvice(beforeAdvice);
proxyFactory.addAdvice(afterReturningAdvice);
proxyFactory.setTarget(userService);
/*
设置接口类型的话,将会默认使用jdk的动态代理JdkDynamicAopProxy来创建代理对象。
否在会使用CGLIB动态代理ObjenesisCglibAopProxy来创建代理类,虽然是使用ObjenesisCglibAopProxy
来创建代理类,但是核心还是 其父类CglibAopProxy来控制,只是使用ObjenesisCglibAopProxy提供的
Objenesis创建对象的技术来创建代理类而已。!!!!!!!!!
*/
proxyFactory.setInterfaces(userService.getClass().getInterfaces());
/*
除此之外可以使用proxyFactory.setOptimize(true)来启动优化代理方式,设置为true的话
如果代理的Target有接口,也会使用CGLIB来创建代理类。
*/
proxyFactory.setOptimize(true);
UserService userServiceProxy = (UserService) proxyFactory.getProxy();
userServiceProxy.registryUser("张三");
}
Ⅱ:AspectJProxyFactory
定义目标类
public class AspectJTarget {
public void test(){
System.out.println("AspectJTarget...");
}
}
定义切面类
@Aspect
public class AspectJTestBean {
@Before(value = "execution(* com.wzy.springstudy.aop.AspectJ.c.*.test())")
public void before(){
System.out.println("before");
}
测试代码
public static void main(String[] args) {
AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory();
设置目标类
aspectJProxyFactory.setTarget(new AspectJTarget());
添加Aspect实例 注意此实例的类一定需要使用@Aspect注解标注
aspectJProxyFactory.addAspect(new AspectJTestBean());
使用AspectJProxyFactory 来构建代理实例
AspectJTarget proxy = aspectJProxyFactory.getProxy();
使用代理类调用业务方法
proxy.test();
}
}
方式2:基于xml配置,使用ProxyFactoryBean
<!--ProxyFactoryBean 使用之前置增强 beforeAdvice-->
<!--1、定义目标bean-->
<bean id="target" class="com.wzy.springstudy.aop.advice.impl.UserServiceImpl"/>
<!--2、定义增强bean-->
<bean id="berforeAdvice" class="com.wzy.springstudy.aop.advice.UserServiceRegistryBeforeAdvice"/>
<!--3、定义所需生成的代理类 使用实现了FactoryBean接口的ProxyFactoryBean-->
<bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--指定目标类-->
<property name="target" ref="target"/>
<!--指定生成的代理类需要实现那些接口。-->
<property name="proxyInterfaces" value="com.wzy.springstudy.aop.advice.UserService"/>
<!--指定需要植入连接点的增强多个增强名称使用“,”号隔开。-->
<property name="interceptorNames" value="berforeAdvice"/>
<!--是否启用代理优化设置为true将会强制使用CGLIB动态代理,
CGLIB创建代理类比较慢,但是创建的代理对象运行的效率
较高,跟jdk动态代理刚好相反,如果代理类是代理的,尽
量使用CGLIB来生成代理类-->
<property name="optimize" value="true"/>
<!--是否对类进行代理,如果设置为true将会使用CGLIB生成代理类。-->
<property name="proxyTargetClass" value="true"/>
<!--生成的代理类是否为单例,默认为true-->
<property name="singleton" value="true"/>
<!--是否暴露生成的代理对象,默认为false,设置为true 可以
在目标类的被增强的连接点(方法)中使用AopContext.currentProxy()
来获取当前生成的代理实例。-->
<property name="exposeProxy" value="true"/>
</bean>
方式3:自动代理构建器,BeanNameAutoProxyCreator 或 DefaultAdvisorAutoProxyCreator 或AnnotationAwareAspectJAutoProxyCreator
Ⅰ:BeanNameAutoProxyCreator
<bean id="dog" class="com.wzy.springstudy.aop.AutoProxyCreator.Dog"/>
<bean id="cat" class="com.wzy.springstudy.aop.AutoProxyCreator.Cat"/>
<bean id="sayHelloBeforeAdvice"
class="com.wzy.springstudy.aop.AutoProxyCreator.SayHelloBeforeAdvice"/>
<!--切面我们就定位目标类的run方法。-->
<bean id="sayHelloAdvisor"
class="com.wzy.springstudy.aop.AutoProxyCreator.SayHelloAdvisor"
p:advice-ref="sayHelloBeforeAdvice"/>
<!--配置BeanNameAutoProxyCreator 自动创建代理器-->
<bean id="beanNameAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames" value="sayHelloAdvisor"/>
<property name="proxyTargetClass" value="true"/>
<!--指定bean name-->
<property name="beanNames" value="cat,dog"/>
<property name="optimize" value="true"/>
</bean>
Ⅱ:DefaultAdvisorAutoProxyCreator
<bean id="dog2" class="com.wzy.springstudy.aop.AutoProxyCreator.Dog"/>
<bean id="cat2" class="com.wzy.springstudy.aop.AutoProxyCreator.Cat"/>
<bean id="sayHelloDefaultAdvisorAutoProxyAdvice"
class="com.wzy.springstudy.aop.AutoProxyCreator.SayHelloBeforeAdvice"/>
<bean id="sayHahahaDefaultAdvisorAutoProxyAdvice"
class="com.wzy.springstudy.aop.AutoProxyCreator.SayHahahaBeforeAdvice"/>
<bean id="regexpMethodPointcutAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="sayHelloDefaultAdvisorAutoProxyAdvice"/>
<!--RegexpMethodPointcutAdvisor 的ClassFilter 为TrueClassFilter.INSTANCE 默认匹配所有的类 此处配置patterns=.*run.* , 就表示为所有bena的以run结尾的方法进行增强。-->
<property name="patterns" value=".*run.*"/>
</bean>
<bean id="staticNamePointcutAdvisor"
class="com.wzy.springstudy.aop.AutoProxyCreator.SayHahahaAdvisor">
<property name="advice" ref="sayHahahaDefaultAdvisorAutoProxyAdvice"/>
</bean>
<!--会容器中所有的Advisor织入到匹配的连接点中-->
<bean id="defaultAdvisorAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
Ⅲ:AnnotationAwareAspectJAutoProxyCreator使用这个代理自动构建既能提供DefaultAdvisorAutoProxyCreator的功能也能提供对aspectj注解的方式来时使用SpringAOP
定义@Aspect切面定义:
@Component
@Aspect
public class AspectJTestBean {
@Before(value = "execution(* com.wzy.springstudy.aop.AutoProxyCreator.*.*())")
public void before(){
System.out.println("before");
}
}
使用xml配置AnnotationAwareAspectJAutoProxyCreator
<bean id="dog2" class="com.wzy.springstudy.aop.AutoProxyCreator.Dog"/>
<bean id="cat2" class="com.wzy.springstudy.aop.AutoProxyCreator.Cat"/>
<bean id="sayHelloDefaultAdvisorAutoProxyAdvice"
class="com.wzy.springstudy.aop.AutoProxyCreator.SayHelloBeforeAdvice"/>
<bean id="sayHahahaDefaultAdvisorAutoProxyAdvice"
class="com.wzy.springstudy.aop.AutoProxyCreator.SayHahahaBeforeAdvice"/>
<bean id="regexpMethodPointcutAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="sayHelloDefaultAdvisorAutoProxyAdvice"/>
<!--RegexpMethodPointcutAdvisor 的ClassFilter 为TrueClassFilter.INSTANCE 默认匹配所有的类此处配置patterns=.*run.* , 就表示为所有bena的以run结尾的方法进行增强。-->
<property name="patterns" value=".*run.*"/>
</bean>
<bean id="staticNamePointcutAdvisor"
class="com.wzy.springstudy.aop.AutoProxyCreator.SayHahahaAdvisor">
<property name="advice" ref="sayHahahaDefaultAdvisorAutoProxyAdvice"/>
</bean>
<!--会容器中所有的Advisor+Aspect语法定义的切面织入到匹配的连接点中-->
<bean id="annotationAwareAspectJAutoProxyCreator"
class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"
p:exposeProxy="true"/>
Ⅳ:使用 <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
使用 <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>来简化AnnotationAwareAspectJAutoProxyCreator配置。
方式4:使用注解驱动
在spring3.1的时候提供了注解@EnableAspectJAutoProxy来激活SpringAop的的自动代理,其实这个注解的作用就是想springIOC容器中注册一个AnnotationAwareAspectJAutoProxyCreator实例到容器中,作用就等价于xml中配置<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>这个标签。
2、在spring boot中是如何自动配置SpringAOP的呢?????
老规矩我们还是来到spring-boot-autoconfigure包下面的spring.factories SPI文件中,查找SringAOP的自动配置类,经过查找我们找到了如下的SpringAOP配置类:
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
我们进入AopAutoConfiguration的源码中:
@Configuration(proxyBeanMethods = false)
配置类条件注解,如果配置了spring.aop.auto=fasle将不会激活当前SpringAOP的自动配置,否则都会激活。
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
如果AopAutoConfiguration 这个配置类被激活了,那么如果当前类路径下存在
org.aspectj.weaver.Advice这个类就会激活当前的内部配置类AspectJAutoProxyingConfiguration,而
这个静态的内部配置类里面又有一个静态内部配置类JdkDynamicAutoProxyConfiguration,这个配置类上面
既然标注了@EnableAspectJAutoProxy 这个注解,这样就清楚了,spring boot自动配置SpringAOP的方式
也就是在使用SpringAOP的注解驱动而已。
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration {
ClassProxyingConfiguration(BeanFactory beanFactory) {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
}
}
源码中显示,当我们的类路径下有org.aspectj.weaver.Advice这个类就能激活AopAutoConfiguration配置类,然后就能开启SpringAOP的注解驱动@EnableAspectJAutoProxy(proxyTargetClass = false) || @EnableAspectJAutoProxy(proxyTargetClass = true),那么我们应该怎样映入org.aspectj.weaver.Advice这个类呢????????
当然我们直接添加如下依赖是可以的:但是前提是我们必须依赖spring-aop这个包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
<scope>compile</scope>
</dependency>
除了需要依赖aspectjweaver这个包外,还需要依赖spring-aop这个包,因此为了简化引入,spring boot为我们提供了spring-boot-starter-aop这个启动组件,来激活SpringAOP自动配置,如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
我们查看spring-boot-starter-aop这个项目的pom.xml文件如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.3.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.8.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
<scope>compile</scope>
</dependency>
</dependencies>
3、以上就是spring boot中自动配置SpringAOP的原理分析。