Spring源码解析系列四:Spring的AOP源码详解

Spring的AOP源码详解

本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应的增强Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理增强实现做准备的过程)

简单使用

@Configuration
@EnableAspectJAutoProxy
public class SpringConfig {
   
}
@Aspect
@Component
@Slf4j
public class LogAspect {
   

   @Pointcut("@annotation(com.lijunhua.advice.log.Logger)")
   public void pc() {
   
   }

   @Around("pc()")
   public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
   
      //1、调用开始...
      String param = JSON.toJSONString(joinPoint.getArgs());
      //开始时间
      long start = System.currentTimeMillis();
      Object result = null;//返回结果 当异常时修改返回结果
      //执行
      try {
   
         result = joinPoint.proceed();
      } catch (Exception e) {
   
         log.error("soa method error,param = {}", param);
         throw e;
      }
      //结束时间
      long end = System.currentTimeMillis();
      log.info("soa method end,start time:{}; end time:{}; Run Time:{}(ms), param={}, result = {}", start, end, (end - start), param, JSON.toJSONString(result, SerializerFeature.DisableCircularReferenceDetect));
      return result;
   }
}

本文只分析AOP的注解实现原理

@EnableAspectJAutoProxy解析

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
   

   /**
    * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
    * to standard Java interface-based proxies. The default is {@code false}.
    */
   boolean proxyTargetClass() default false;

   /**
    * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
    * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
    * Off by default, i.e. no guarantees that {@code AopContext} access will work.
    * @since 4.3.1
    */
   boolean exposeProxy() default false;

}
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
   

   private final Log logger = LogFactory.getLog(getClass());
   /**
    * Register, escalate, and configure the AspectJ auto proxy creator based on the value
    * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
    * {@code @Configuration} class.
    */
   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   

      // 就是在往传入的BeanDefinitionRegistry registry中注册BeanDefinition。
      // 注册了BeanDefinition之后,Spring就会去实例化这个Bean,从而达到AspectJAutoProxy作用
      // 添加到Spring上下文中的AnnotationAwareAspectjAutoProxyCreator对象
      //  AnnotationAwareAspectjAutoProxyCreator对象其实就是这个类型InstantiationAwareBeanPostProcessor
      // 在createbean时调用resolveBeforeInstantiation(beanName, mbdToUse),
      //  会首先调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法,可以在此处返回代理的对象
      if(logger.isInfoEnabled()){
   
         logger.info("加入AOP处理的类的bd到bdMap中,该类名为:AnnotationAwareAspectJAutoProxyCreator");
      }
      AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

      AnnotationAttributes enableAspectJAutoProxy =
            AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
      if (enableAspectJAutoProxy != null) {
   
         if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
   
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
         }
         if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
   
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
         }
      }
   }

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

   return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
      Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
   

   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   // 如果注册表中已经存在beanName=org.springframework.aop.config.internalAutoProxyCreator的bean,
   // 则按优先级进行选择。
   // beanName=org.springframework.aop.config.internalAutoProxyCreator,可能存在的beanClass有三种,
   // 按优先级排序如下:
   // InfrastructureAdvisorAutoProxyCreator、
   // AspectJAwareAdvisorAutoProxyCreator、
   // AnnotationAwareAspectJAutoProxyCreator
   if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
   
      // 拿到已经存在的bean定义
      BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
      // 如果已经存在的bean的className与当前要注册的bean的className不相同,则按优先级进行选择
      if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
   
         // 拿到已经存在的bean的优先级
         int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
         // 拿到当前要注册的bean的优先级
         int requiredPriority = findPriorityForClass(cls);
         if (currentPriority < requiredPriority) {
   
            // 如果当前要注册的bean的优先级大于已经存在的bean的优先级,则将bean的className替换为当前要注册的bean的className,
            apcDefinition.setBeanClassName(cls.getName());
         }
         // 如果小于,则不做处理
      }
      // 如果已经存在的bean的className与当前要注册的bean的className相同,则无需进行任何处理
      return null;
   }

   // 如果注册表中还不存在,则新建一个Bean定义,并添加到注册表中
   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   // 设置了order为最高优先级
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   // 注册BeanDefinition,beanName为org.springframework.aop.config.internalAutoProxyCreator
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

小结

  1. 利用@Import导入AspectJAutoProxyRegistrar类,该类实现ImportBeanDefinitionRegistrar接口
  2. 在解析AspectJAutoProxyRegistrar的registerBeanDefinitions方法是注册BeanDefinition,这里面注册了AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,后续实例化以及初始化该类,在处理AOP的增强逻辑。

@Aspect的解析

即形成Advisor的过程

解析的时机

初次从spring容器中获取第一个bean时,调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法时,调用createBean方法—>resolveBeforeInstantiation方法—>调用容器中所有的InstantiationAwareBeanPostProcessor的实现类的postProcessBeforeInstantiation方法

真正解析步骤

最终调到AbstractAutoProxyCreator的postProcessBeforeInstantiation方法

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   
   Object cacheKey = getCacheKey(beanClass, beanName);

   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
   
      if (this.advisedBeans.containsKey(cacheKey)) {
   
         return null;
      }
      // bean的类是aop基础设施类 || 使用@Aspect注解
      // 在shouldSkip中初始化了所有的AOP的advisor以及事务的advisor
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
   
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }

   // Create proxy here if we have a custom TargetSource.
   // Suppresses unnecessary default instantiation of the target bean:
   // The TargetSource will handle target instances in a custom fashion.
   TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
   if (targetSource != null) {
   
      if (StringUtils.hasLength(beanName)) {
   
         this.targetSourcedBeans.add(beanName);
      }
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
      Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   return null;
}

分析shouldSkip方法

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
   
   // Consider optimization by caching the list of the aspect names
   // 找到容器中所有的Advisor,含AOP和Spring事务
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   for (Advisor advisor : candidateAdvisors) {
   
      // 名称相同
      if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
   
         return true;
      }
   }
   return super.shouldSkip(beanClass, beanName);
}

最终调到AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors方法

protected List<Advisor> findCandidateAdvisors() {
   
   // Add all the Spring advisors found according to superclass rules.
   // 添加根据父类规则找到的所有advisor。
   List<Advisor> advisors = super.findCandidateAdvisors(
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值