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

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取 2000+ 道 Java 面试题

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

继承图如下:

20191123100163\_1.png

可以看到该类实现了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源码深度解析》


来源:http://ddrv.cn/a/88268

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring AOP实现原理笔记(二) — 源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏