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

目录

一、前言

二、源码分析

三、特别说明


一、前言

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进行了改造的?

经过上一章的分析,我们知道getBean方法作为调用起点,完成了Bean的创建和依赖注入,构造了一个完整的Bean返回给用户使用,那么AOP对Bean的改造应当是在依赖注入之后,返回给用户之前,下面带着这个疑问,回到源码中继续学习。

二、源码分析

在AbstractAutowireCapableBeanFactory类的doCreateBean方法中,我们可以发现如下代码:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
 
    /**
     * 真正开始创建Bean
     */
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
         
        ......

        // 初始化bean
        Object exposedObject = bean;
        try {
            // 这里开始进行依赖注入
            populateBean(beanName, mbd, instanceWrapper);
            // 初始化bean,执行Initialization BeanPostProcessor
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }
        ......
        // 返回Bean实例,这里已经完成了依赖注入
        return exposedObject;
    }
}

在这里,我们发现在依赖注入之后,返回给用户之前,调用了initializeBean方法,下面一起看看这个方法的实现:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {	
    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        } else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 在初始化前调用Initialization后置处理器before方法
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 调用Bean配置的init-method
            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()) {
            // 在初始化后调用Initialization后置处理器after方法
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

    /**
     * 调用Initialization后置处理器postProcessBeforeInitialization方法
     */
    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

    /**
     * 调用Initialization后置处理器postProcessAfterInitialization方法
     */
    @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的类继承图(省略了部分接口):

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

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    ...

    /**
     * before初始化
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    /**
     * 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方法来解析元素,比如对于<aop:config>标签,则会使用AopNamespaceHandler进行解析,这里可以参考Spring源码学习【二】IOC容器的初始化(二)BeanDefinition载入 

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

configureAutoProxyCreator(parserContext, element);

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值