spring boot 源码_Spring-Boot-Starter-AOP源码解析

打开spring-boot-starter-aop的jar包:

fb043be8fa9249ce1d4ebfd5600937e4.png

里面一个类也没有,只是在pom中添加了几个依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>2.1.7.RELEASE</version>
  <scope>compile</scope>
</dependency>
  <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>5.1.9.RELEASE</version>
  <scope>compile</scope>
</dependency>
  <dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.4</version>
  <scope>compile</scope>
</dependency>

说明配置类是在spring-boot-autoconfigure里面:

7d5852efc0f145e5fb7107c0bce401e8.png

看下AopAutoConfiguration:

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

  @Configuration
  @EnableAspectJAutoProxy(proxyTargetClass = false)
  @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
      matchIfMissing = false)
  public static class JdkDynamicAutoProxyConfiguration {
  }

  @Configuration
  @EnableAspectJAutoProxy(proxyTargetClass = true)
  @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
      matchIfMissing = true)
  public static class CglibAutoProxyConfiguration {
  }
}

代码很简单,首先看下@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class }),只有在EnableAspectJAutoProxy、Aspect、Advice和AnnotatedElement这些类存在的时候,配置才起作用,上一篇我们讲了只要加入aspectjweaver的jar,然后添加EnableAspectJAutoProxy就可以启用AOP,一样的判断逻辑。

@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true):只有定义了spring.aop.auto并且值是true才启用,如果没定义那么默认就是true,一般我们都不会定义,因此只要加入了这个依赖默认AOP就是启用的。
继续看下面定义的2个bean:

@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", 
name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)

如果定义了spring.aop.proxy-target-class这个属性并且值是false的话,那么就启用EnableAspectJAutoProxy(proxyTargetClass = false),如果没定义默认值是false,

同理看下面一个bean的定义:

@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", 
name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)

如果定义了spring.aop.proxy-target-class这个属性并且值是true的话,那么就启用EnableAspectJAutoProxy(proxyTargetClass = true),如果没定义默认值是true

也就是说,如果我们没有明确的定义这个属性,那么SpringBoot的aop默认会启用@EnableAspectJAutoProxy(proxyTargetClass = true)。proxyTargetClass = true的意思是使用Cglib代理,因此,在SpringBoot中,默认是使用Cglib代理,而不是像Spring中那样,如果实现了接口就使用JDK的代理,没有实现接口就是用Cglib代理

我们来证明下:

首先是使用Spring的方式:

//这是个接口
package com.github.xjs.aopdemo.service;
public interface IService {
    void print(String msg);
}
//接口的一个实现
package com.github.xjs.aopdemo.service;
public class Service1 implements IService {
    @Override
    public void print(String msg){
        log.info("Service1 print:{}",  msg);
    }
}
//它并没有实现IService接口
package com.github.xjs.aopdemo.service;
public class Service2 {
    public void print(String msg){
        log.info("Service2 print:{}",  msg);
    }
}
//这是切面
package com.github.xjs.aopdemo.springdemo;
@Aspect
public class DemoAdvice {
    @Pointcut("execution(* com.github.xjs.aopdemo.service.*.*(..))")
    public void pointCut(){
    }
    @Before("pointCut()")
    public void before(){
        log.info("---------before-------");
    }
}
//配置类
@Configuration
@EnableAspectJAutoProxy
public class DemoApp {
  @Bean
  public DemoAdvice demoAdvice(){
    return new DemoAdvice();
  }
  @Bean
  public IService iService(){
    return new Service1();
  }
  @Bean
  public Service2 service2(){
    return new Service2();
  }
}
//测试一下
public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(DemoApp.class);
    IService s1 = ctx.getBean(IService.class);
    Service2 s2 = ctx.getBean(Service2.class);
    //class com.sun.proxy.$Proxy17
    System.out.println(s1.getClass());
    //class com.github.xjs.aopdemo.service.Service2$$EnhancerBySpringCGLIB$$de245da0
    System.out.println(s2.getClass());
  }

现在我们换成SpringBoot的方式:

@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringBootDemoTest {
    @Autowired
    IService service;
    @Test
    public void testAop(){
        System.out.println(service.getClass());
        //class com.github.xjs.aopdemo.service.Service1$$EnhancerBySpringCGLIB$$f107fe5e
    }
}

以上可以看的很清楚了,Spring方式的时候,service1是使用的JDK的动态代理,SpringBoot的时候,Service1是使用的Cglib代理。

继续看EnableAspectJAutoProxy的代码,其实这就跟SpringBoot没关系了:

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
  //这个控制是否使用cglib,默认是false
  boolean proxyTargetClass() default false;
  //这个是说是否可以用AopContext来到当前的代理对象,具体的使用场景可以参考前一篇
  boolean exposeProxy() default false;
}

看到我们非常熟悉的@Import,继续看AspectJAutoProxyRegistrar:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  @Override
  public void registerBeanDefinitions(
      AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    //这一行注册了AOP注解处理的Bean
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    //这是获取EnableAspectJAutoProxy注解里面的值
    AnnotationAttributes enableAspectJAutoProxy =
        AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
    if (enableAspectJAutoProxy != null) {
      if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
      }
      if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
        AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
      }
    }
  }
}

AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary:

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
        BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    } else {
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", -2147483648);
        beanDefinition.setRole(2);
        registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
        return beanDefinition;
    }
}

以上实际上就是注册了一个名字叫org.springframework.aop.config.internalAutoProxyCreator,类型是AnnotationAwareAspectJAutoProxyCreator的Bean。

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {}
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {}
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator{}
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport 
    implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {}

AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor,里面就是具体的AOP的处理了,非常复杂!主要做的事情就是解析Advice,生成代理,下一篇我们通过一些具体的案例来看下AOP具体的应用场景,敬请关注。

源码下载:https://github.com/xjs1919/enumdemo 下面的 aop-demo

欢迎扫码加关注:

c97806eff126885d76baa4e7fbc5e992.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值