美文网首页IT@程序员猿媛
【Spring 笔记】AOP 创建代理对象相关整理

【Spring 笔记】AOP 创建代理对象相关整理

作者: 58bc06151329 | 来源:发表于2020-02-13 19:20 被阅读0次

    文前说明

    作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

    本文仅供学习交流使用,侵权必删。
    不用于商业目的,转载请注明出处。

    1. 概述

    • Spring 为目标 bean 筛选到合适的通知器(可查看 【Spring 笔记】AOP 通知筛选相关整理 了解)后,再通过 创建代理对象 的方式将 Advisor(通知器)所持有的 Advice(通知)织入到 bean 的某些方法前后。

    proxy-target-class

    • 在 Spring AOP 配置中,proxy-target-class 属性可以影响 Spring 创建代理对象的类型。
    <!-- spring.xml -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    
    <aop:config proxy-target-class="true">
        <aop:aspect id="xxx" ref="xxxx">
        </aop:aspect>
    </aop:config>
    
    • 默认情况下 proxy-target-class 属性为 false。
      • 当目标 bean 实现了接口时,Spring 会基于 JDK 动态代理 为目标 bean 创建代理对象。
      • 若未实现任何接口,Spring 则会通过 CGLIB 创建代理对象。
    • 当 proxy-target-class 属性设为 true 时,则会强制 Spring 通过 CGLIB 的方式创建代理对象,即使目标 bean 实现了接口。
    • 详细可以查看 Java 动态代理实现 了解。

    optimize

    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <!-- 只为后缀为"impl"的bean生产代理 -->
            <property name="beanNames" value="*impl"></property>
            <!-- 增强 -->
            <property name="interceptorNames" value="aServiceAdvisor"></property>
            <!-- 是否对代理策略进行优化 -->
            <property name="optimize" value="true"></property>
        </bean>
    
    • 是否对代理策略进行优化,默认情况下 optimize 值为 false。

    2. 原理

    // AbstractAutoProxyCreator.java
    public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
            implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
        
        @Override
        // bean 初始化后置处理方法 
        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;
        }
        
        protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        ......
            /*
             * 若 specificInterceptors != null,即 specificInterceptors != DO_NOT_PROXY,
             * 则为 bean 生成代理对象,否则直接返回 bean
             */ 
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                // 1. 创建代理
                Object proxy = createProxy(
                        bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                /*
                 * 返回代理对象,此时 IOC 容器输入 bean,得到 proxy。此时,
                 * beanName 对应的 bean 是代理对象,而非原始的 bean
                 */ 
                return proxy;
            }
            ......
        }
    
        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);
    
        /*
         * 默认配置下,或用户显式配置 proxy-target-class = "false" 时,
         * 这里的 proxyFactory.isProxyTargetClass() 也为 false
         */
        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                /*
                 * 检测 beanClass 是否实现了接口,若未实现,则将 
                 * proxyFactory 的成员变量 proxyTargetClass 设为 true
                 */ 
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
    
        // specificInterceptors 中若包含有 Advice,此处将 Advice 转为 Advisor
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);
    
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
    
        // 创建代理
        return proxyFactory.getProxy(getProxyClassLoader());
    }
    
    // ProxyFactory.java
    public Object getProxy(ClassLoader classLoader) {
        // 先创建 AopProxy 实现类对象,然后再调用 getProxy 为目标 bean 创建代理对象
        return createAopProxy().getProxy(classLoader);
    }
    
    // ProxyCreatorSupport.java
    protected final synchronized AopProxy createAopProxy() {
            if (!this.active) {
                this.activate();
            }
            // 返回 AopProxy
            return this.getAopProxyFactory().createAopProxy(this);
    }
    
    • 步骤 1 中,如果通知器数组不为空,则为 bean 生成代理对象。

    AopProxy

    • 为目标 bean 创建代理对象前,需要先创建 AopProxy 对象。
    // AopProxy.java
    public interface AopProxy {
    
        /** 创建代理对象 */
        Object getProxy();
        
        Object getProxy(ClassLoader classLoader);
    }
    
    • Spring 中两个类实现了 AopProxy
    AopProxy 体系

    DefaultAopProxyFactory

    • getAopProxyFactory() 方法获取 DefaultAopProxyFactory 工程类。
    // DefaultAopProxyFactory.java
    public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    
        @Override
        public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            /*
             *   config.isOptimize() 是否对代理策略进行优化
             *   config.isProxyTargetClass() 检测 proxyTargetClass 的值
             *   hasNoUserSuppliedProxyInterfaces(config) 目标 bean 是否实现了接口
             */
            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);
                }
                // 创建 CGLIB 代理,ObjenesisCglibAopProxy 继承自 CglibAopProxy
                return new ObjenesisCglibAopProxy(config);
            }
            else {
                // 创建 JDK 动态代理
                return new JdkDynamicAopProxy(config);
            }
        }
    }
    
    • Spring 根据 bean 是否实现接口,以及一些配置决定使用 AopProxy 何种实现类为目标 bean 创建代理对象。

    getProxy

    • JdkDynamicAopProxy 为例,为目标 bean 创建代理对象。
    // JdkDynamicAopProxy.java
    public Object getProxy() {
        return getProxy(ClassUtils.getDefaultClassLoader());
    }
    
    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);
        
        // 调用 newProxyInstance 创建代理对象
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
    

    相关文章

      网友评论

        本文标题:【Spring 笔记】AOP 创建代理对象相关整理

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