Spring AOP源码分析

前言

通过之前的俩篇文章,我们大体上已经知道如何使用SpringAOP了,同时也了解到了SpringAOP底层使用的技术实现(JDK提供的动态代理和CGLib字节码增强技术)。至此,我们来想一个问题,SpringAOP到底是如何实现的呢?

猜测

首先我们知道SpringAOP运用的是代理模式,那么就一定是为目标对象生成一个代理对象,然后在一个合适的时机,将目标对象从IOC容器里替换成了我们已经加强过的代理对象。顺着这条思路我们来跟着源码进行解读。


本文中用到的代码示例

进行源码解读,可以通过debug来一步步分析。给出本次的代码示例,大家可以根据这份示例代码进行debug解读。

俩个service接口以及相关的实现类

public interface OrderService {
    Order createOrder(String username, String product);

    Order queryOrder(String username);
}
package com.suxin.aop.service.impl;

import com.suxin.aop.model.Order;
import com.suxin.aop.service.OrderService;

public class OrderServiceImpl implements OrderService {

    private static Order order = null;

    public Order createOrder(String username, String product) {
        order = new Order();
        order.setUsername(username);
        order.setProduct(product);
        return order;
    }

    public Order queryOrder(String username) {
        return order;
    }
}

public interface UserService {
    User createUser(String firstName, String lastName, int age);

    User queryUser();
}
package com.suxin.aop.service.impl;

import com.suxin.aop.model.User;
import com.suxin.aop.service.UserService;

public class UserServiceImpl implements UserService {
    private static User user = null;

    public User createUser(String firstName, String lastName, int age) {
        user = new User();
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setAge(age);
        return user;
    }
    public User queryUser() {
        return user;
    }
}

紧接着是俩个advice(增强):

package com.suxin.aop.advice;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;
import java.util.Arrays;

public class LogArgsAdvice implements MethodBeforeAdvice {
    // 方法调用前输出 调用方法名字和参数
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("准备执行方法: "+ method.getName()+", 参数列表: " + Arrays.toString(args));
    }
}
package com.suxin.aop.advice;

import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;

public class LogResultAdvice implements AfterReturningAdvice {
    // 方法调用后输出结果
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(method.getName()+"方法返回: " + returnValue);
    }
}

然后进行XML配置:

    
    
    
    
    
    
    

    
    
        
        
    
    
    
        
        
    

    

以及main的运行代码:

package com.suxin.aop;

import com.suxin.aop.service.OrderService;
import com.suxin.aop.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aops.xml");
        UserService userService = (UserService)context.getBean("userServiceImpl");
        userService.createUser("Tom","Paul",35);
        userService.queryUser();
        OrderService orderService = (OrderService)context.getBean("orderServiceImpl");
        orderService.createOrder("DDD","买个糖葫芦");
        orderService.queryOrder("DDD");
    }
}

至此,示例代码就已经贴完了,沿用的是SpringAOP初始里的代码。大家可以参考这份示例代码进行debug调试。

贴一下控制台输出打印吧:

八月 15, 2019 10:36:38 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@685f4c2e: startup date [Thu Aug 15 10:36:38 CST 2019]; root of context hierarchy
八月 15, 2019 10:36:38 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [aops.xml]
准备执行方法: createUser, 参数列表: [Tom, Paul, 35]
queryUser方法返回: com.suxin.aop.model.User@77167fb7
准备执行方法: createOrder, 参数列表: [DDD, 买个糖葫芦]
queryOrder方法返回: com.suxin.aop.model.Order@1fe20588

解读

还记得XML配置里面将DefaultAdvisorAutoProxyCreator纳入到了SpringIOC容器的管理里面。它让我们的配置在IOC容器里的advisor(通知器)自动生效,我们来看一下这个类的继承图:

Spring AOP源码分析_第1张图片
DefaultAdvisorAutoProxyCreator继承结构.png

可以看到没,DefaultAdvisorAutoProxyCreator最终是一个实现了BeanPostProcessor接口的类,而该接口有俩个方法:

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

这俩个方法的执行时机在IOC创建bean的三个方法(createBeanInstance、populateBean和initializeBean)里的initializeBean方法里。看一下源码:

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        // ......

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // postProcessBeforeInitialization方法的执行时机
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 调用bean配置里的inti-method="XXX"关联的方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            // postProcessAfterInitialization执行的时机
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

通过源码我们可以看到,其实执行增强的时机就在postProcessAfterInitialization方法里,会在初始化bean的最后进行增强并且进行替换。
我们来看一下这块方法的实现(实现方法是在DefaultAdvisorAutoProxyCreator的父类AbstractAutoProxyCreator里面):

//来自于AbstractAutoProxyCreator,294行
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                //关注一下这个方法:如果需要,为 bean 生成代理对象
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

//深入到wrapIfNecessary方法里面来:

// 来自于AbstractAutoProxyCreator,333行
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        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;
        }

        // 获取对应这个bean需要的拦截器(其实就是各种通知器advisor)
        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:

// 来自于AbstractAutoProxyCreator,437行
    protected Object createProxy(
            Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }
        //创建代理工厂实例
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);
        // ......
        // 是否不管有没有继承接口,都使用cglib技术
        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                // 有接口的,调用一次或多次:proxyFactory.addInterface(ifc);
                // 没有接口的,调用:proxyFactory.setProxyTargetClass(true);
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
        // 所有跟bean相关的advisor(如果是advice或者interceptor都会包装成advisor)
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        for (Advisor advisor : advisors) {
            proxyFactory.addAdvisor(advisor);
        }

        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        // 继续关注这个方法
        return proxyFactory.getProxy(getProxyClassLoader());
    }

通过上面的源码解读我们可以知道上面的流程就是创建一个ProxyFactory,并且进行相关的属性赋值,然后通过是这个实例进行getProxy方法

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

先看createAopProxy方法:

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }

继续看getAopProxyFactory()方法,发现返回的是一个DefaultAopProxyFactory,我们直接看createAopProxy这个方法。

// 来自于DefaultAopProxyFactory,50行
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                // 返回JDK的AOP动态代理对象
                return new JdkDynamicAopProxy(config);
            }
            // 返回CGLibd的AOP动态代理对象
            return new ObjenesisCglibAopProxy(config);
        }
        else {
            // 返回JDK的AOP动态代理对象
            return new JdkDynamicAopProxy(config);
        }
    }

至此,我们就把重点放在了JdkDynamicAopProxyObjenesisCglibAopProxy上面
大家可以通过源码来看到JdkDynamicAopProxy是实现了InvocationHandler接口的类。

还是回到我们的源码解读进度来,返回了JdkDynamicAopProxy/ObjenesisCglibAopProxy对象以后开始调用createAopProxy方法。(我现在拿JdkDynamicAopProxy作为例子来看)
再把上面的代码拿下来回看一下

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

然后看到调用的是getProxy方法:

    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        // 关注一下这里,是不是跟我们之前聊过的JDK提供的动态代理创建代理对象方法是一致的。
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

我们看到Proxy.newProxyInstance静态方法最后一个参数传的是this,也就是自身,因为JdkDynamicAopProxy也实现了InvocationHandler接口。
我们来看一下它是如何实现InvocationHandler接口方法invoke的:

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

        TargetSource targetSource = this.advised.targetSource;
        Class targetClass = null;
        Object target = null;

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
            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;

            if (this.advised.exposeProxy) {
                // 如果设置了 exposeProxy,那么将 proxy 放到 ThreadLocal 中
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            // May be null. Get as late as possible to minimize the time we "own" the target,
            // in case it comes from a pool.
            target = targetSource.getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }

            // 创建一个 链,包含所有要执行的 advice
            List 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.
            if (chain.isEmpty()) {
                // We can skip creating a MethodInvocation: just invoke the target directly
                // Note that the final invoker must be an InvokerInterceptor so we know it does
                // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
            }
            else {
                // 关注一下这里 先创建一个ReflectiveMethodInvocation 然后执行方法,得到返回值
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // 关注一下这个方法,有空咱们再详细聊聊
                retVal = invocation.proceed();
            }

            // Massage return value if necessary.
            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);
            }
        }
    }
 
 

有兴趣的朋友可以去看一下上面的ReflectiveMethodInvocation类里面的proceed方法,是一个递归回调。
至于ObjenesisCglibAopProxy其实也是继承CglibAopProxy,而 CglibAopProxy 继承了 AopProxy。有兴趣的自己去看一下吧,这里就不多说了。


小结一下吧:通过上面的分析,可以看出SpringAOP的生成代理对象以及替换时机是在BeanPostProcessor的postProcessAfterInitialization方法上。而创建代理涉及到了俩个类JdkDynamicAopProxyObjenesisCglibAopProxy。对应的之前说过的SpringAOP代理的实现是基于JDK提供的动态代理和CGLib技术实现。我们也分析了一下JdkDynamicAopProxy,它是一个继承了InvocationHandler接口方法的实现类。

多说几句,这篇文章可能要配合之前的SpringAOP俩篇文章看过之后再看,可能才得以理解。当然更需要点IOC容器的基础知识点。

你可能感兴趣的:(Spring AOP源码分析)