美文网首页
Spring AOP源码分析

Spring AOP源码分析

作者: 耐得千事烦 | 来源:发表于2019-08-15 16:03 被阅读0次

    前言

    通过之前的俩篇文章,我们大体上已经知道如何使用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配置:

        <!-- 俩个接口的实现类纳入到IOC容器的管理里-->
        <bean id="userServiceImpl" class="com.suxin.aop.service.impl.UserServiceImpl" />
        <bean id="orderServiceImpl" class="com.suxin.aop.service.impl.OrderServiceImpl" />
        
        <!-- 实现的俩个增强纳入到IOC容器管理里-->
        <bean id="logArgsAdvice" class="com.suxin.aop.advice.LogArgsAdvice" />
        <bean id="logResultAdvice" class="com.suxin.aop.advice.LogResultAdvice" />
    
        <!-- 记录create*方法的传参-->
        <bean id="logArgsAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="logArgsAdvice" /><!-- 设置增强-->
            <property name="pattern" value="com.suxin.aop.service.*.create.*" /><!-- 正则匹配-->
        </bean>
        <!-- 记录query*方法的返回值-->
        <bean id="logResultAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <property name="advice" ref="logResultAdvice" /><!-- 设置增强-->
            <property name="pattern" value="com.suxin.aop.service.*.query.*" /><!-- 正则匹配-->
        </bean>
    
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
    

    以及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(通知器)自动生效,我们来看一下这个类的继承图:

    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);
            // <aop:config proxy-target-class="true">......</aop:config>
            // 是否不管有没有继承接口,都使用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<Object> 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源码分析

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