Spring AOP源码分析二

上一篇讲述了Spring AOP开发步骤和@EnableAspectJAutoProxy注解的两个属性,这一篇讲解@EnableAspectJAutoProxy注解的源码。
Spring AOP源码分析一

@Configuration
@ComponentScan("edu.hzb.aop")
//proxyTargetClass=true,表示采用Cglib的方式创建代理
//exposeProxy=true,表示将对象的代理对象存放在ThreadLocal中
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class AppConfig {
}

进入到@EnableAspectJAutoProxy注解中:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
   boolean proxyTargetClass() default false;

   boolean exposeProxy() default false;
}`

创建代理对象

@Import注解导入了AspectJAutoProxyRegistray这对象,而AspectJAutoProxyRegistray实现了ImportBeanDefinitionRegistrar接口,实现了registerBeanDefinitions方法,最后会注册AnnotationAwareAspectJAutoProxyCreator这个BeanDefinition

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      //注册AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor
      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);
         }
      }
   }

}

根据ctrl + shirt + alt + u快捷键查看AnnotationAwareAspectJAutoProxyCreator的类图接口,发现它实现了BeanPostProcessor接口,所以会在Bean的初始化前后执行对应的加工方法。(一般会选择在初始化方法之后进行加工,因为此时完成了初始化操作)

public interface BeanPostProcessor {
   @Nullable
   default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 	{
      return bean;
   }

   @Nullable
   default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 	{
      return bean;
   }

}

进入到AnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInitialization(Object bean, String beanName)方法

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      //判断是否因为循环引用已经创建了代理
      //比如A类中注入B的代理对象,B类中又注入A的代理对象,此时在解决循环引用的时候就会创建代理对象
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         //核心方法,创建代理
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

进入到wrapIfNecessary(bean, beanName, cacheKey)方法中

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   //安全校验
   //判断bean是否为空
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }
   //判断当前bean是否是切面,因为切面对应的类也需要@Component注解,但是肯定不可能为切面创建代理
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
   }
   //用于处理事务的
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // Create proxy if we have advice.
   //获取创建代理所需要的切面(这里叫拦截器)
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   //如果当前原始对象的切面不为空,肯定是需要为其创建代理对象,进行增强
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      //创建代理的核心代码
      Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}

进入到为原始对象创建代理对象的核心方法createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean))

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
      @Nullable Object[] specificInterceptors, TargetSource targetSource) {

   if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
      AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
   }

   //通过ProxyFactory创建代理对象
   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);

   if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }

   //根据额外功能和切入点组装切面
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   //设置切面和原始对象,就可以知道为哪一个原始对象进行增强
   proxyFactory.addAdvisors(advisors);
   proxyFactory.setTargetSource(targetSource);
   //空实现
   customizeProxyFactory(proxyFactory);

   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }
   //真正创建代理,getProxy方法有JDK和Cglib两种实现
   return proxyFactory.getProxy(getProxyClassLoader());
}

proxyFactory.getProxy(getProxyClassLoader())方法执行完成后,就根据JDK或Cglib方式创建好了代理对象。这里仅仅只是创建好了代理对象,额外功能对原始方法的增强是要在运行过程中,动态的将原始对象的方法和额外功能进行整合


public static void main(String[] args) {
     /*
        在创建ApplicationContext时,因为UserService默认是单例对象,所在创建工厂时就会创建UserService对应的
        Bean对象,在初始化后就会执行BeanPostProcessor的后置加工postProcessAfterInitialization方法,这时就	     会创建好了UserService的代理对象
    */
    ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    /**
        UserService默认是单例对象,上面创建工厂时就会执行完UserService的整个生命周期,这里就可以直接从单例池		中获取UserService的代理对象;
        UserService如果是多实例对象,则在getBean方式执行时会重新走一下创建UserService的Bean对象的生命周期流	     程,最终也可以得到UserService的代理对象
    */
    UserService userService = (UserService) context.getBean("userService");
    //执行该方法时,才会动态的将UserService的原始对象的方法和额外功能进行整合到一起
    userService.printAge();
}

这里就可以看出动态代理是在运行过程中将原始方法和额外功能进行整合,中间执行了大量的代码,所以效率上肯定不如静态代理,但是灵活性和可维护性却远远超过静态代理。

原始方法和额外功能整合

上面的测试类只是创建了userService的代理对象userServiceProxy,当执行userService.printAge()这行代码时,就需要将原始对象userService的printAge()和符合切入点表达式的额外功能动态的整合在一起执行。

因为UserService是接口,所以Spring默认会通过jdk动态代理方式创建代理对象。执行userService.printAge()方法就会进入到JdkDynamicAopProxy.java文件的invoke方法中:

@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   Object oldProxy = null;
   boolean setProxyContext = false;

   //原始对象(这里就是userService)
   TargetSource targetSource = this.advised.targetSource;
   Object target = null;

   try {
      //判断equals方法是否要代理
      if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
         // The target does not implement the equals(Object) method itself.
         return equals(args[0]);
      }
      //判断hashCode方法是否要代理
      else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
         // The target does not implement the hashCode() method itself.
         return hashCode();
      }
      else if (method.getDeclaringClass() == DecoratingProxy.class) {
         // There is only getDecoratedClass() declared -> dispatch to proxy config.
         return AopProxyUtils.ultimateTargetClass(this.advised);
      }
      else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
            method.getDeclaringClass().isAssignableFrom(Advised.class)) {
         // Service invocations on ProxyConfig with the proxy config...
         return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
      }

      Object retVal;
      //处理exposeProxy属性,是否要暴露代理,如果需要暴露代理就会把代理对象存放在ThreadLocal中
      if (this.advised.exposeProxy) {
         // Make invocation available if necessary.
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
      }

      // Get as late as possible to minimize the time we "own" the target,
      // in case it comes from a pool.
      //获取原始对象和对应类型
      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);

      // Get the interception chain for this method.
      //获取目标方法method的拦截器(也就是根据切入点表达式,过滤出要给当前method方法加上的一系列额外功能)
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

      // Check whether we have any advice. If we don't, we can fallback on direct
      // reflective invocation of the target, and avoid creating a MethodInvocation.
      //如果chain为空,表示原始对象的原始方法method不需要加上对应的额外功能,就直接执行原始对象的method就行
       if (chain.isEmpty()) {
         Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
         retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
      }
      else {
         // We need to create a method invocation...
         //将原始方法和额外功能整合在一起
         MethodInvocation invocation =
               new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
         // Proceed to the joinpoint through the interceptor chain.
         //执行原始方法和额外功能
         retVal = invocation.proceed();
      }

      // 处理方法返回类型
      Class<?> returnType = method.getReturnType();
      if (retVal != null && retVal == target &&
            returnType != Object.class && returnType.isInstance(proxy) &&
            !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
         // Special case: it returned "this" and the return type of the method
         // is type-compatible. Note that we can't help if the target sets
         // a reference to itself in another returned object.
         retVal = proxy;
      }
      else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
         throw new AopInvocationException(
               "Null return value from advice does not match primitive return type for: " + method);
      }
      return retVal;
   }
   finally {
      if (target != null && !targetSource.isStatic()) {
         // Must have come from TargetSource.
         targetSource.releaseTarget(target);
      }
      if (setProxyContext) {
         // Restore old proxy.
         AopContext.setCurrentProxy(oldProxy);
      }
   }
}

retVal = invocation.proceed()这行代码用于完成原始方法和额外功能的执行:

public Object proceed() throws Throwable {
   // 判断拦截器(额外功能)是否执行完了,如果额外功能都执行完了就执行原始方法
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      //执行原始方法
      return invokeJoinpoint();
   }
   //获取下一个拦截器(额外功能)
   Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
   if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
      // Evaluate dynamic method matcher here: static part will already have
      // been evaluated and found to match.
      InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
      Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
      if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
         return dm.interceptor.invoke(this);
      }
      else {
         return proceed();
      }
   }
   else {
      // 注意这里是在实现类中递归的调用invoke方法,就会执行下一个额外功能或原始方法
      // 因为不可能先执行完所有的额外功能,再执行原始方法,一定是要按照前置增强  -> 原始方法  -> 后置增强这样的顺序处理
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

在将原始方式和额外功能整合过程中,一定是要按照前置增强 -> 原始方法 -> 后置增强这样的顺序执行,所以在return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)这行代码中,invoke接口的实现中就会按照额外功能和原始方法的执行顺序执行:

invoke接口有很多的实现类,如图:

在这里插入图片描述

以前置增强MethodBeforeAdviceInterceptor和后置增强AspectJAfterAdvice为例:

MethodBeforeAdviceInterceptor.java

@SuppressWarnings("serial")
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

   private final MethodBeforeAdvice advice;
    
   public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
      Assert.notNull(advice, "Advice must not be null");
      this.advice = advice;
   }

   @Override
   public Object invoke(MethodInvocation mi) throws Throwable {
      //执行前置增强的额外功能before
      this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
      //这里就会递归执行proceed()方法,就会执行原始方法
      return mi.proceed();
   }

}

AspectJAfterAdvice.java

public class AspectJAfterAdvice extends AbstractAspectJAdvice
      implements MethodInterceptor, AfterAdvice, Serializable {

   public AspectJAfterAdvice(
         Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {

      super(aspectJBeforeAdviceMethod, pointcut, aif);
   }


   @Override
   public Object invoke(MethodInvocation mi) throws Throwable {
      try {
         //递归调用proceed()方法,这里会执行原始方法
         return mi.proceed();
      }
      finally {
         //执行后置增强额外功能
         invokeAdviceMethod(getJoinPointMatch(), null, null);
      }
   }

   @Override
   public boolean isBeforeAdvice() {
      return false;
   }

   @Override
   public boolean isAfterAdvice() {
      return true;
   }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值