Spring 4.3 源码分析之 配置式Aop (一)

1. Spring Aop 配置式Aop Demo

上篇中通过手动写代码, 将 Pointcut, MethodInterceptor, ProxyFactory, TargetBean 组装起来, 最终通过 ProxyFactory.getProxy() 来获取代理的对象; 而本篇将结合 Spring 中的 FactoryBean 结合起来, 只需要在 xml 中配置少许 信息就能对目标对象生成代理对象, 配置的信息如下:









    com.lami.foodie.aop.aop1.KK
    
    simpleMethodInterceptor

PS: 上面配置文件对应的类在上篇中已存在

2. Spring Aop 配置式Aop 组件 ProxyFactoryBean

ProxyFactoryBean 是通过 FactoryBean 来针对指定的 targetBean 来创建动态代理对象 (PS: FactoryBean 是 Spring IOC 中针对创建指定对象的抽象工厂, 毕竟有些类的创建过程是很复杂的, 所以出现了 FactoryBean 这个角色), 其主要有一下属性:

/**
 * This suffix in a value in an interceptor list indicates to expand globals.
 */
public static final String GLOBAL_SUFFIX = "*";

protected final Log logger = LogFactory.getLog(getClass());

// 从字面意思上, 下面是拦截器, 其实不然, 下面支持获取指定前缀的 advice/MethodInterceptor, 当然也可以在下面的数组的最后一位设置 target 的名字 (PS: 这在checkInterceptorNames中解析)
private String[] interceptorNames;

// 代理的目标类 target, 这个 String 主要是通过xml 设置, 或通过 checkInterceptorNames 方法上
private String targetName;

// 自动获取 target 上的 interface
private boolean autodetectInterfaces = true;

// PS: 这里的 singleton 指的是 advice 是否是 singleton
private boolean singleton = true;

// 前置 Spring aop 中主要使用的是 MethodInterceptor, 而在 xml 中配置的  标签中解析出来的都是 advice, 这时需要对应的适配器 -> 将 advice 适配成 MethodInterceptor
// 这里的 advisorAdapterRegistry 中主要是将 advice, MethodInterceptor 包装成 Advisor, 与将 Advisor 转成 MethodInterceptor
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();

// 设置是否 动态代理的配置信息是否变化
private boolean freezeProxy = false;

// 创建动态代理时使用的 classLoader
private transient ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();

// 配置是否已经配置了 classLoader
private transient boolean classLoaderConfigured = false;

// 创建动态时使用的  BeanFactory
private transient BeanFactory beanFactory;

// 标示动态代理中的 advisorChain 链是否已经创建好
/** Whether the advisor chain has already been initialized */
private boolean advisorChainInitialized = false;

// 这个类其实就是动态代理创建的最终对象
/** If this is a singleton, the cached singleton proxy instance */
private Object singletonInstance;

以上这些属性中最重要的还是 interceptorNames(拦截器链), targetName(代理的类), 将 advice/advisor 转换成 MethodInterceptor 的适配器注册工厂 advisorAdapterRegistry, 有了以上的属性, 则再通过下面的的两个方法就能创建代理对象:

public Object getObject() throws BeansException {
    // 这里初始化通知器链
    initializeAdvisorChain();
    // 这里对 Singleton prototype 的类型进行区分, 生成对应的 Proxy
    if (isSingleton()) {
        return getSingletonInstance();
    }
    else { // prototype 模式则每次创建一个类
        if (this.targetName == null) {
            logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
                    "Enable prototype proxies by setting the 'targetName' property.");
        }
        return newPrototypeInstance();
    }
}

// 动态代理对象 singletonInstance
private synchronized Object getSingletonInstance() {
    if (this.singletonInstance == null) {
        this.targetSource = freshTargetSource();                // 返回对应的 target
        // 自动获取需要动态代理的接口
        if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
            // Rely on AOP infrastructure to tell us what interfaces to proxy.
            Class targetClass = getTargetClass();
            if (targetClass == null) {
                throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
            }
            // 这里设置代理对象的接口
            setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));     // 获取 targetClass 的所有的 interface
        }
        // Initialize the shared singleton instance.
        super.setFrozen(this.freezeProxy);
        // 注意这里的方法将会使用 ProxyFactory 来生成
        // 通过 createAopProxy 返回 合适的 AopProxy(JdkDynamicAopProxy, CglibAopProxy), 并将 AopProxy 传如 getProxy 方法中进行动态代理
        this.singletonInstance = getProxy(createAopProxy());
    }
    return this.singletonInstance;
}
3. Spring Aop 配置式Aop ProxyFactoryBean 创建对象流程

整个创建代理对象的整个过程是在 ProxyFactoryBean 的 getObject 方法中触发的, 大体流程如下:

1. 初始化 AdvisorChain
    1.1 循环遍历 interceptorNames, 从 BeanFactory 中获取对应 Advice, MethodInterceptor, 通过 AdvisorAdaptorRegistry 包装成 Advisor 加入到 AdvisorChain 里面
2. 调用 getSingletonInstance方法, 创建动态代理对象
    2.1 根据 targetName 从 BeanFactory 中拿到对应对象
    2.2 获取 target 类实现的所有接口 <- 为代理这些接口准备数据
    2.3 DefaultAopProxyFactory 根据 AdvisedSupport 来创建合适的 AopProxy (JdkDynamicAopProxy, CglibAopProxy) , 判断的条件主要是 optimize, targetClass, hasNoUserSuppliedProxyInterfaces
    2.4 Aop 根据已经获取到的 Advisor, Target 等信息创建代理对象
(PS: 其实理解了上篇的编程式 Aop, 则这里的 ProxyFactoryBean 就很好理解了; 另外插一下 aop 很重要, Spring 里面的很多特性都是基于 aop, 比如 事务, 缓存, Hystrix 等)
4. 总结:

本篇讲述通过 ProxyFactoryBean 来创建代理对象, 整个创建过程其实和上篇差不多, 也就是说 ProxyFactoryBean 只是做了 MethodInterceptor 的自动获取, 以及 通过 ProxyFactory 创建代理对象, 而问题也在 ProxyFactoryBean 中, 从这个类中我们发现, 只要需要创建一个动态代理对象, 则就需要配置一个 ProxyFactoryBean <-- 而在一般项目中需要创建很多动态代理对象, 可想而知这是多么可怕的事情, 所以就出现了 AbstractAutoProxyCreator(自动获取 BeanFactory 中的所有 Advice/MethodInterceptor, 并针对所有符合 Pointcut 的对象创建代理对象, 这也是下篇将叙述的内容)。

5. 参考:

Spring Aop核心源码分析
Spring技术内幕
Spring 揭秘
Spring 源码深度分析
开涛 Spring 杂谈
伤神 Spring 源码分析
Spring源码情操陶冶

你可能感兴趣的:(Spring 4.3 源码分析之 配置式Aop (一))