Spring源码学习【六】AOP原理解析(一)代理对象的生成

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

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

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

目录

一、前言

二、源码分析

三、特别说明

一、前言

AOP(Aspect Oriented Programming 面向切面编程)是Spring框架的核心功能之一,关于AOP中一些概念的理解可以参考 SpringAOP概念及其使用 ,下面以一个简单的例子作为Spring AOP源码学习的起点。

首先,定义一个切面类CustomAspect,如下所示:

    public class CustomAspect {

        public void before() {
            System.out.println("Before custom operation");
        }

        public void after() {
            System.out.println("After custom operation");
        }

    }

然后,在配置文件中定义Bean、切面、切入点、通知等,如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

        <bean id="a" class="greedystar.entity.A" lazy-init="true">
            <property name="name" value="Alvin"/>
            <property name="id" value="123"/>
            <property name="roles">
                <list>
                    <value>USER</value>
                    <value>ADMIN</value>
                </list>
            </property>
        </bean>

        <!-- 定义切面bean -->
        <bean id="aspect" class="greedystar.entity.CustomAspect"/>

        <aop:config proxy-target-class="true">
            <!-- 引入切面 -->
            <aop:aspect id="aspect" ref="aspect">
                <!-- 定义切点 -->
                <aop:pointcut id="say" expression="execution(* greedystar.entity.A.say(..))"/>
                <!-- 定义通知 -->
                <aop:before method="before" pointcut-ref="say"/>
                <aop:after method="after" pointcut-ref="say"/>
            </aop:aspect>
        </aop:config>

    </beans>

最后,通过如下代码获取到IOC容器中名为 a 的Bean:

    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
    A a = (A) applicationContext.getBean("a");
    a.say();

运行结果如下:

    Before custom operation
    123 Alvin [USER, ADMIN]
    After custom operation

从上面的例子中可以看到,say方法在执行前后分别执行了CustomAspect中的before和after方法,于是我们就需要思考一个问题:Spring是在什么地方对Bean进行了改造的?

下面带着这个问题,回到源码中继续学习。

二、源码分析

回想前面几节的学习可以发现:Bean在创建的过程中使用了后置处理器,允许处理器在Bean实例化前后进行一些处理,顺着这个思路我们回到 Spring源码学习【四】依赖注入过程 (2)createBean 中,在AbstractAutowireCapableBeanFactory类中我们可以发现如下代码:

    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

        ...

        /**
         * 创建Bean
         */
        @Override
        protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
            ...
            try {
                // 允许在实例化前进行处理
                // 如果返回值不为空,表示配置了后置处理器,并且修改了bean
                // 则返回一个代理,而不是bean实例
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                if (bean != null) {
                    return bean;
                }
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex);
            }
            ...
        }
    }

在这里,我们发现官方注释很明确的指出:这里可能会对Bean进行修改,并返回一个修改后的代理对象。顺着这个思路,我们深入到这个方法的实现中,代码如下:

    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

        ...

        /**
         * Bean实例化前的处理
         */
        @Nullable
        protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
            Object bean = null;
            if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
                if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                    Class<?> targetType = determineTargetType(beanName, mbd);
                    if (targetType != null) {
                        // 调用before实例化后置处理器
                        bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                        if (bean != null) {
                            // 调用after初始化后置处理器
                            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                        }
                    }
                }
                mbd.beforeInstantiationResolved = (bean != null);
            }
            // 返回Bean对象,若为null则表示未进行Bean修改,否则表示对Bean进行了修改
            return bean;
        }

        /**
         * 调用before实例化后置处理器
         */
        @Nullable
        protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                    if (result != null) {
                        return result;
                    }
                }
            }
            return null;
        }

        /**
         * 调用after初始化后置处理器
         */
        @Override
        public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

            Object result = existingBean;
            for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
                Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
                if (current == null) {
                    return result;
                }
                result = current;
            }
            return result;
        }

    }

在上面的代码中我们发现最终调用了BeanPostProcessor接口的相关方法,我们以接口的实现类AspectJAwareAdvisorAutoProxyCreator为例看看后置处理器的实现,首先来看一下AspectJAwareAdvisorAutoProxyCreator的类继承图(省略了部分接口):

20191102100701\_1.png

从图中可以看到AspectJAwareAdvisorAutoProxyCreator间接实现了BeanPostProcessor接口,接口方法的实现在其父类AbstractAutoProxyCreator中,如下所示:

    public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

        ...

        /**
         * before实例化后置处理器
         */
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            Object cacheKey = getCacheKey(beanClass, beanName);
            // 跳过无需代理的场景,返回null则表示未对bean进行修改
            if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
                if (this.advisedBeans.containsKey(cacheKey)) {
                    return null;
                }
                if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                    this.advisedBeans.put(cacheKey, Boolean.FALSE);
                    return null;
                }
            }
            // 对bean进行增强,创建代理,返回代理对象,阻止后续bean的默认实例化行为
            TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
            if (targetSource != null) {
                if (StringUtils.hasLength(beanName)) {
                    this.targetSourcedBeans.add(beanName);
                }
                // 获取通知数组
                Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
                // 创建代理
                Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            }

            return null;
        }

        /**
         * after初始化后置处理器
         */
        @Override
        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) {
            // 处理不需要生成代理的情况
            if (StringUtils.hasLength(beanName) && 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;
            }

            // 获取通知数组
            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;
        }

        /**
         * 创建代理
         */
        protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
            if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
                AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
            }
            // 代理工厂,提供了非配置方式的编程式使用方式
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.copyFrom(this);
            // proxyFactory.isProxyTargetClass() 默认为false
            if (!proxyFactory.isProxyTargetClass()) {
                // 是否代理目标类,也就是对<aop:config>节点的proxy-target-class属性进行判断
                // 为true时表示通过CGLIB进行代理
                if (shouldProxyTargetClass(beanClass, beanName)) {
                    proxyFactory.setProxyTargetClass(true);
                }
                // 为false时表示通过JDK进行代理,需要实现接口
                else {
                    evaluateProxyInterfaces(beanClass, proxyFactory);
                }
            }
            // 创建通知数组
            Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
            proxyFactory.addAdvisors(advisors);
            proxyFactory.setTargetSource(targetSource);
            customizeProxyFactory(proxyFactory);
            proxyFactory.setFrozen(this.freezeProxy);
            if (advisorsPreFiltered()) {
                proxyFactory.setPreFiltered(true);
            }
            // 创建并返回代理对象
            // 根据配置或由Spring自动决定使用JDK或CGLIB方式生成代理对象
            // 最终实现在DefaultAopProxyFactory类中
            return proxyFactory.getProxy(getProxyClassLoader());
        }

    }

这段代码返回了一个代理对象,从而阻止了Bean默认的实例化操作,代理对象的创建由ProxyFactory完成,下面让我们来看一看ProxyFactory的具体实现,代码如下:

    public class ProxyFactory extends ProxyCreatorSupport {

        public Object getProxy(@Nullable ClassLoader classLoader) {
            // 这里的createAopProxy()方法定义在父类ProxyCreatorSupport中
            return createAopProxy().getProxy(classLoader);
        }

    }

ProxyCreatorSupport代码如下:

    public class ProxyCreatorSupport extends AdvisedSupport {

        protected final synchronized AopProxy createAopProxy() {
            if (!this.active) {
                activate();
            }
            // 这里的getAopProxyFactory默认返回一个DefaultAopProxyFactory对象
            return getAopProxyFactory().createAopProxy(this);
        }

    }

DefaultAopProxyFactory代码如下:

    public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

        /**
         * 根据配置或由Spring自动优化决定使用JDK动态代理还是CGLIB生成代理对象
         */
        @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)) {
                    return new JdkDynamicAopProxy(config);
                }
                return new ObjenesisCglibAopProxy(config);
            }
            else {
                return new JdkDynamicAopProxy(config);
            }
        }
    }

从上面的代理中可以看到,最终调用了JdkDynamicAopProxy或ObjnesisCglibAopProxy的getProxy方法获得了一个代理对象,这里以JdkDynamicAopProxy为例看一看具体实现:

    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

        @Override
        public Object getProxy(@Nullable 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);
            return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
        }

    }

可以看到最终通过Java的反射机制创建了代理对象并返回给了用户,至此AOP代理对象的创建过程就完成了。

三、特别说明

对BeanDefinition解析比较了解的同学可能记得解析工作是委托给BeanDefinitionParserDelegate完成的,在这个类的parseCustomElement方法中,会根据<>元素标签的命名空间取得相应的NamespaceHandler,并通过Handler的parse方法来解析元素,比如对于标签,则会使用AopNamespaceHandler进行解析,这里可以参考Spring源码学习【二】IOC容器的初始化(二)BeanDefinition载入

在AopNamespaceHanlder中定义了一系列的BeanDefinitionParser,当解析时,会调用ConfigBeanDefinitionParser的parse方法,在这个方法中有如下代码:

    configureAutoProxyCreator(parserContext, element);

    private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
        AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
    }

这部分代码表示Spring默认提供了一个AspectJ的代理生成器,这就是为什么上文中以AspectJAwareAdvisorAutoProxyCreator为例分析代理对象的生成过程。


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring源码学习【六】AOP原理解析(一)代理对象的生成

评论 抢沙发

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

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

支付宝扫一扫打赏

微信扫一扫打赏