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

前言

有一点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 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实现原理)