springboot9--->spring-boot自动配置springAOP原理分析

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的原理分析。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值