Spring AOP实现原理笔记(二) -- 源码分析

1、注册AnnotationAwareAspectJAutoProxyCreator

首先要了解Spring解析XML配置文件时,遇到自定义节点是如何解析的。可以参考Spring自定义XML标签解析及其原理分析

当Spring遇到这个标签的时候,它会拿到这个标签的命名空间,发现是http://www.springframework.org/schema/aop,接着打开aop的jar包中会发现一个META-INF目录,在该目录下有一个spring.handlers文件,打开后就会发现如下:

http://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

所以对于aop标签的解析就交给了AopNamespaceHandler去处理。

public class AopNamespaceHandler extends NamespaceHandlerSupport {
        ...
    public void init() {
        this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
        this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
        this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
        this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
    }
}

可以看到aspectj-autoproxy这个属性是由AspectJAutoProxyBeanDefinitionParser来处理。

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
    ...
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
        this.extendBeanDefinition(element, parserContext);
        return null;
    }
    ...
}

AopNamespaceUtils类

public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
//【步骤1】注册或升级AutoProxyCreator定义beanName为org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition
    BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//【步骤2】对proxy-target-class以及expose-proxy属性的处理
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//【步骤3】注册组件并通知,便于监听器做进一步处理
    registerComponentIfNecessary(beanDefinition, parserContext);
}

跟踪上面的【步骤1】,如下:

AopConfigUtils类:

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

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
  ...
  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 {
//新建一个BeanDefinition
      RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
      beanDefinition.setSource(source);
      beanDefinition.getPropertyValues().add("order", Integer.valueOf(-2147483648));
      beanDefinition.setRole(2);
      registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
      return beanDefinition;
  }
}

上面目的是往BeanDefinitionRegistry添加一个AnnotationAwareAspectJAutoProxyCreator类的beanDefinition,beanbeanName为org.springframework.aop.config.internalAutoProxyCreator(相关属性可参考AbstractBeanDefinition属性一览)。如果存在同样beanName的beanDefinition,那就根据优先级来决定是否要改变该beanDefinition的beanClassName,其中优先级为(InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator)。

接着上面的【步骤2】会对proxy-target-class以及expose-proxy属性进行处理,如下

AopNamespaceUtils类

private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
    if(sourceElement != null) {
     boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute("proxy-target-class")).booleanValue();
     if(proxyTargetClass) {
         AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
     }
     boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute("expose-proxy")).booleanValue();
     if(exposeProxy) {
         AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
    }
}

AopConfigUtils类

public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
    if(registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
        BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
        definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
    }
}
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
    if(registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
        BeanDefinition definition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
        definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
    }
}

实际就是根据配置改变beanDefinition中的属性。

2、分析AnnotationAwareAspectJAutoProxyCreator

继承图如下:

《Spring AOP实现原理笔记(二) -- 源码分析》

可以看到该类实现了BeanPostProcessor接口,那它就可以对实例化后的bean进行后置增强;同时它还实现了InstantiationAwareBeanPostProcessor接口,该接口是BeanPostProcessor的其中一个子接口,实现这个接口,可以在Spring实例化bean之前,有机会返回自己的bean实例来中断Spring实例化bean。所以有两个地方有机会给bean进行增强。(可以参考Spring IOC实现原理笔记(三) – 加载bean实例

看其中eanPostProcessor接口中的postProcessAfterInitialization它是如何实现的

父类AbstractAutoProxyCreator

//bean实例化后
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if(bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        if(!this.earlyProxyReferences.contains(cacheKey)) {
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //已经处理过
    if(beanName != null && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    } else if(Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {//不需要代理
        return bean;
    } 
//给定的bean类是基础设施类(如Advice等)或配置了不需要自动代理就不需要创建代理类
else if(!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
        //如果存在增强方法则创建代理
        Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
        //如果获取到了增强则需要针对增强创建代理
        if(specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //创建代理
            Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    } else {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
}
  1. 获取增强器需要遍历在beanFactory中所有注册的bean,找出声明了AspectJ注解的类,然后对其进行增强器的提取,把提取结果加入缓存。
  2. 获得所有增强器后,就要筛选出使用于当前的bean的增强器。
  3. 筛选出增强器后,就是创建代理类了。

下面看看如何创建代理类的:

protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
    ProxyFactory proxyFactory = new ProxyFactory();
    //获取当前类中的相关属性
    proxyFactory.copyFrom(this);
    if(!proxyFactory.isProxyTargetClass()) {
        if(this.shouldProxyTargetClass(beanClass, beanName)) {
            //使用CGLib代理
            proxyFactory.setProxyTargetClass(true);
        } else {
            //添加接口
            this.evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }
    //封装增强器
    Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
    for(Advisor advisor:advisors) {
    //加入增强器
        proxyFactory.addAdvisor(advisor);
    }
    //设置要代理的类
    proxyFactory.setTargetSource(targetSource);
    this.customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);
    if(this.advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }
    return proxyFactory.getProxy(this.getProxyClassLoader());
}

public Object getProxy(ClassLoader classLoader) {
    return this.createAopProxy().getProxy(classLoader);
}

protected final synchronized AopProxy createAopProxy() {
    ...
    return this.getAopProxyFactory().createAopProxy(this);
}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//不优化 & proxy-target-class属性不为true & 实现了接口
    if(!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
        return new JdkDynamicAopProxy(config);//JDK代理
    } else {
        Class<?> targetClass = config.getTargetClass();
       ...
        //如果目标类不是接口,也不是代理类就使用CGLib
        return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass)?new ObjenesisCglibAopProxy(config):new JdkDynamicAopProxy(config));
    }
}

上面把创建代理类的任务交给了ProxyFactory(用法可参考Spring AOP实现原理笔记(一) – 简单介绍),其中返回的代理分JdkDynamicAopProxy和ObjenesisCglibAopProxy.

3. JdkDynamicAopProxy分析

JdkDynamicAopProxy实现了InvocationHandler接口,所以主要逻辑在invoke方法,从上面可以看到是通过其getProxy方法拿到代理实例的,代码如下

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
...
public Object getProxy(ClassLoader classLoader) {
       Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
       this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
       return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       Object oldProxy = null;
       boolean setProxyContext = false;
       TargetSource targetSource = this.advised.targetSource;
       Class<?> targetClass = null;
       Object target = null;
       try {
           ...
           Object retVal;
           if(!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
               retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
               return retVal;
           }
        //有时候目标对象内部的自我调用将无法实施切面中的增强,则需要通过侧属性暴露代理
           if(this.advised.exposeProxy) {
               oldProxy = AopContext.setCurrentProxy(proxy);
               setProxyContext = true;
           }
           target = targetSource.getTarget();
           if(target != null) {
               targetClass = target.getClass();
           }
        //获取当前方法的拦截器链
           List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
           if(chain.isEmpty()) {
            //为空就直接反射调用
               retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
           } else {
            //将拦截器封装在ReflectiveMethodInvocation,再用其proceed进行链式调用
               MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
               retVal = invocation.proceed();
           }

           Class<?> returnType = method.getReturnType();
           if(retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
               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()) {
               targetSource.releaseTarget(target);
           }
           if(setProxyContext) {
               AopContext.setCurrentProxy(oldProxy);
           }
       }
   }
...
}

看链式调用增强器部分

ReflectiveMethodInvocation类

public Object proceed() throws Throwable {
    if(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return this.invokeJoinpoint();
    } else {
        Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
            //动态匹配方法,匹配则执行拦截器,不匹配就不执行
            return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)?dm.interceptor.invoke(this):this.proceed();
        } else {
        //普通拦截器,就直接调用拦截器
            return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
        }
    }
}

4.ObjenesisCglibAopProxy分析

class ObjenesisCglibAopProxy extends CglibAopProxy {
    ...
    protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
        Class<?> proxyClass = enhancer.createClass();
        Object proxyInstance = null;
        if(objenesis.isWorthTrying()) {
            try {
                proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
            } catch (Throwable var7) {
                ...省略logger
            }
        }
        if(proxyInstance == null) {
            try {
                proxyInstance = this.constructorArgs != null?proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs):proxyClass.newInstance();
            } catch (Throwable var6) {
                ...省略throw
            }
        }
        ((Factory)proxyInstance).setCallbacks(callbacks);
        return proxyInstance;
    }
}

上面没有看到getProxy方法,所以是在其父类中

CglibAopProxy类

public Object getProxy(ClassLoader classLoader) {
    try {
        Class<?> rootClass = this.advised.getTargetClass();
        Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
        Class<?> proxySuperClass = rootClass;
        int x;
        if(ClassUtils.isCglibProxyClass(rootClass)) {
            proxySuperClass = rootClass.getSuperclass();
            Class<?>[] additionalInterfaces = rootClass.getInterfaces();
            for(Class<?> additionalInterface:additionalInterfaces) {
                this.advised.addInterface(additionalInterface);
            }
        }
        //验证Class
        this.validateClassIfNecessary(proxySuperClass, classLoader);
        //创建及配置Enhancer
        Enhancer enhancer = this.createEnhancer();
        if(classLoader != null) {
            enhancer.setClassLoader(classLoader);
            if(classLoader instanceof SmartClassLoader && ((SmartClassLoader)classLoader).isClassReloadable(proxySuperClass)) {
                enhancer.setUseCache(false);
            }
        }
        enhancer.setSuperclass(proxySuperClass);
        enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
//获取拦截器(将advised属性封装成DynamicAdvisedInterceptor等并加入Callback)
        Callback[] callbacks = this.getCallbacks(rootClass);
        Class<?>[] types = new Class[callbacks.length];
        for(x = 0; x < types.length; ++x) {
            types[x] = callbacks[x].getClass();
        }
        enhancer.setCallbackFilter(new CglibAopProxy.ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
        enhancer.setCallbackTypes(types);
//这里调用了上面子类的方法生成代理类
        return this.createProxyClassAndInstance(enhancer, callbacks);
    } catch...
}

CGLib用法需要实例化一个Enhancer,然后自定义拦截器加入Callback中,在调用代理时直接激活拦截器中的intercept方法(可参考样例Spring AOP实现原理笔记(一) – 简单介绍)。DynamicAdvisedInterceptor屎其中一种了拦截器,如下:

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
...
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
          Object oldProxy = null;
          boolean setProxyContext = false;
          Class<?> targetClass = null;
          Object target = null;
          Object var11;
          try {
              if(this.advised.exposeProxy) {
                  oldProxy = AopContext.setCurrentProxy(proxy);
                  setProxyContext = true;
              }
              target = this.getTarget();
              if(target != null) {
                  targetClass = target.getClass();
              }
        //获取拦截器链
              List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
              Object retVal;
              if(chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
            //拦截器链为空则直接激活原方法
                  retVal = methodProxy.invoke(target, args);
              } else {
            //进链逐个调用
                  retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();
              }
              retVal = CglibAopProxy.processReturnType(proxy, target, method, retVal);
            return retVal;
          } finally {
              if(target != null) {
                  this.releaseTarget(target);
              }
              if(setProxyContext) {
                  AopContext.setCurrentProxy(oldProxy);
              }
          }
      }
...
}

上面的实现和JDK方式实现代理中的invoke方法大同小异,都是首先构造链,然后封装此链进行串联调用。JDK中直接构造ReflectiveMethodInvocation,而CGLib使用CglibMethodInvocation(CglibMethodInvocation继承ReflectiveMethodInvocation)。

PS:Spring4.0内联了objenesis库,使得使用CGLib代理不再要求目标类提供无参构造函数。

参考

Spring源码(4.2.2.RELEASE)

《Spring源码深度解析》

    原文作者:Spring Cloud
    原文地址: https://blog.csdn.net/seasonLai/article/details/82712235
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞