美文网首页
浅析AOP实现原理(3)Spring AOP实现原理

浅析AOP实现原理(3)Spring AOP实现原理

作者: 挡不住的柳Willow | 来源:发表于2019-06-19 18:38 被阅读0次

    前言

    有一点Spring基础的同学应该都知道,Spring的动态代理默认使用的是JDK动态代理(对于非接口的类,用cglib,与JDK动态代理类似,这里不多做解释),不清楚JDK动态代理的点这里。并且,我们知道通过jdk动态代理,我们可以拿到一个代理后的对象,而Spring的bean实例化过程,就涉及到代理对象的替换

    Spring Bean的生命周期

    想知道Spring是如何实现的动态代理,必须对bean的生命周期和实例化过程有初步了解。笔者通过阅读源码,得知一个bean的实例化过程,是由一系列的BeanPostProcessor(后置处理器)处理的,在bean实例化之前的注解解析,实例化过程中确定构造器,实例化后的属性注入,属性注入完的初始化步骤,分别由特定的后置处理器来完成。
    如果要在Spring当中实现aop动态代理,笔者认为主要有两种思路:

    • 1、实例化之前将BeanDefinition中的class替换为代理类,可以通过自定义BeanFactoryPostProcessor或者ImportBeanDefinitionRegisterar来实现
    • 2、实例化完成之后,通过自定义的BeanPostProcessor将对象替换成代理对象

    由于jdk动态代理和cglib动态代理,都只提供了获取代理对象的方法,因此我们可以猜测Spring是利用第二种方式实现的。

    猜想验证

    下面是一段aop切面的demo:

    @Aspect
    @Component
    public class MyAspect {
        @Autowired
        private MyService myService;
    
        @Pointcut("execution(* com.lwl.controller.MyController.testAop(..))")
        public void testAop(){}
    
        @Around("testAop()")
        public Object aopWeaveing(ProceedingJoinPoint joinPoint) throws Throwable {
           //代理代码,忽略
        }
    }
    

    下面是被代理的方法和类:

    @RestController
    @RequestMapping("/aop")
    public class MyController {
        @GetMapping("test")
        @AssertLogin
        public String testAop(){
            //业务代码,忽略
        }
    }
    

    bean的实例化过程主要发生在context的refresh方法中的finishBeanFactoryInitialization方法,其中
    调用了DefaultLisableBeanFactory的preInstantiateSingletons,通过getBean(beanName)来实例化bean
    因此我们跟踪到执行了自定义beanPostProcessor的AbstractAutowireCapableBeanFactory的initializeBean方法当中:

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
            //忽略不重要的代码
            //wrappedBean即bean对象
            Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
               //调用beanPostProcessor的postProcessBeforeInitialization方法
                wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
            }
    
            try {
                //调用bean中实现的afterPropertiesSet或被@PostConstuct注解修饰的方法,即初始化方法
                invokeInitMethods(beanName, wrappedBean, mbd);
            }
            if (mbd == null || !mbd.isSynthetic()) {
              //调用beanPostProcessor的postProcessAfterInitialization方法
                wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
            }
            return wrappedBean;
        }
    

    这里需要明确的是,beanPostProcessor的两个方法postProcessBeforeInitialization和postProcessAfterInitialization都能够替换对象,区别在于postProcessBeforeInitialization在bean执行初始化方法之前执行,简单思考一下,我们对对象进行代理时,很可能需要用到该bean对象初始化之后的属性,因此我们猜测代理的过程发生在初始化之后的postProcessAfterInitialization过程中。
    笔者将断点打在调用applyBeanPostProcessorsAfterInitialization方法之前,可以看到此时的wrapperBean还是MyController


    断点往下走,执行完applyBeanPostProcessorsAfterInitialization方法,发现wrappedBean已经变成了CGLib动态代理对象:

    这就验证了我们之前的猜测

    实现原理分析

    我们进入applyBeanPostProcessorsAfterInitialization方法看看spring到底做了什么事

        public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                throws BeansException {
    
            Object result = existingBean;
             //遍历容器中所有的beanPostProcessor,执行postProcessAfterInitialization方法
            for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
                Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }
    

    可以看到该方法中遍历了spring容器里所有的beanPostProcessor,并挨个执行postProcessAfterInitialization。由于笔者是在平时开发的springboot环境中随便写了一个aop类做调试,因此此时的容器中有非常多的后置处理器,简单看一下一共有三十个:


    image.png

    目前我们能确定的是,一定是某一个后置处理器执行完了postProcessAfterInitialization方法,才将对象替换成了代理对象,那如何从这么多的beanPostProcessor中找到那个凶手?两种方法:

    • 1、还是用之前打断点的方法,看看哪一个后置处理器执行完以后对象发生了改变,但是这里有三十多个后置处理器,作为一个有追求的程序员考虑到算法时间复杂度为O(n),不行这个方法需要优化
    • 2、靠猜- -笔者死磕源码的经历,大部分情况靠猜,事实上百分之八十都能猜对。这三十个beanPostProcessor中,从名字上看,似乎只有数组下标为5的AnnotationAwareAspectJAutoProxyCreator看起来比较可疑(又是Aspect又是AutoProxy的)
      因此我们将断点条件修改为只有beanPostProcessor为该对象时才暂停:


      image.png

      继续调试,成功进入断点,执行之前为MyController


      image.png
      断点执行完以后对象变成了Cglib代理对象:
      image.png
      猜想再次被验证了,那么我们的重点就转换为查看这个beanPostProcessor中究竟做了什么,一路跟踪:
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
            if (bean != null) {
                Object cacheKey = getCacheKey(bean.getClass(), beanName);
                if (!this.earlyProxyReferences.contains(cacheKey)) {
                 //重点看这个方法,它返回了代理后的对象
                    return wrapIfNecessary(bean, beanName, cacheKey);
                }
            }
            return bean;
        }
    
    
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
                  //根据bean的类型和bean的名称,获取与该类相关的切面
            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;
            }
            return bean;
        }
    
    
    protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                @Nullable Object[] specificInterceptors, TargetSource targetSource) {
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.copyFrom(this);
             //从切面对象中提取我们定义的增强逻辑代码,构造成proxyFactory代理工厂
            Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
            proxyFactory.addAdvisors(advisors);
            proxyFactory.setTargetSource(targetSource);
            customizeProxyFactory(proxyFactory);
    
            proxyFactory.setFrozen(this.freezeProxy);
            if (advisorsPreFiltered()) {
                proxyFactory.setPreFiltered(true);
            }
                    //通过代理工厂创建代理
            return proxyFactory.getProxy(getProxyClassLoader());
        }
    
    //该方法为proxyFactory中的getProxy
    public Object getProxy(@Nullable ClassLoader classLoader) {
            return createAopProxy().getProxy(classLoader);
        }
    

    调试发现createAopProxy()返回了一个CglibAopProxy,说明此时使用的是cglib动态代理



    而CglibAopProxy的getProxy里面就是我们非常熟悉的cglib动态代理的代码了:

    public Object getProxy(@Nullable ClassLoader classLoader) {
                 //rootClass即MyController.class
                Class<?> rootClass = this.advised.getTargetClass();
                Class<?> proxySuperClass = rootClass;
                Enhancer enhancer = 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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
    
               //根据要代理的类生成callback,这个是重点
                Callback[] callbacks = getCallbacks(rootClass);
                Class<?>[] types = new Class<?>[callbacks.length];
                for (int x = 0; x < types.length; x++) {
                    types[x] = callbacks[x].getClass();
                }
                enhancer.setCallbackFilter(new ProxyCallbackFilter(
                        this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
                enhancer.setCallbackTypes(types);
                return createProxyClassAndInstance(enhancer, callbacks);
        }
    
    
    
    private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
             //advised即之前创建好的proxyFactory,包含了我们交给spring管理的所有Aspect
            boolean exposeProxy = this.advised.isExposeProxy();
            boolean isFrozen = this.advised.isFrozen();
            boolean isStatic = this.advised.getTargetSource().isStatic();
            //将切面构造成Callback,主要看这个类
            Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
                 ... ...
        }
    
    
    //构造的callback:
    private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
           //重点看重写的intercept方法
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object oldProxy = null;
                boolean setProxyContext = false;
                Object target = null;
                TargetSource targetSource = this.advised.getTargetSource();
                try {
                 //如果代理对象被设置为可以暴露,则将当前的代理对象注入
                    if (this.advised.exposeProxy) {
                        oldProxy = AopContext.setCurrentProxy(proxy);
                        setProxyContext = true;
                    }
                    target = targetSource.getTarget();
                    Class<?> targetClass = (target != null ? target.getClass() : null);
                  //把切面的增强逻辑转换成list
                    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                    Object retVal;
                 //如果没有增强逻辑,则直接执行原来的方法
                    if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                        Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                        retVal = methodProxy.invoke(target, argsToUse);
                    }
                    else {
                   //有增强逻辑,则根据spring aop配置规则确定执行顺序
                        retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
                    }
                    retVal = processReturnType(proxy, target, method, retVal);
                    return retVal;
                }
            }
        }
    

    总结

    Spring的aop,是在bean被实例化并初始化之后,通过beanPostProcessor的postProcessAfterInitialization,通过cglib(jdk动态代理),在实际逻辑执行前后插入我们的增强逻辑

    相关文章

      网友评论

          本文标题:浅析AOP实现原理(3)Spring AOP实现原理

          本文链接:https://www.haomeiwen.com/subject/hitlqctx.html