spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二

前言

一、ConfigurationClassPostProcessor之BeanFactoryPostProcessor身份

  • 它的这个身份同样起到了非常重要的作用: 为全配置类添加cglib代理,防止以@Bean的方式创建bean时出现重复调用相同逻辑的问题。 接下来我们按照如下demo一起探究它。

二、项目demo

2.1 项目全景图

spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第1张图片

2.1.1 AppConfig

spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第2张图片

2.1.2 Bean1

spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第3张图片

2.1.3 Bean2

spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第4张图片

2.1.4 Entryspring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第5张图片

2.2 运行结果

2.2.1 AppConfig类中无@Configuration注解的运行结果

spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第6张图片

2.2.1 AppConfig类中有@Configuration注解的运行结果

spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第7张图片

2.3 解释运行结果

情形 运行结果 原因
AppConfig中无@Configuration注解 打印了两次"creating bean1" 运行的没有一点毛病, 按照正常逻辑, 执行了两次(spring创建Bean1的时候调用了一次, 创建Bean2的时候又调用了一次)创建bean的方法, 所以输出两次"creating bean1", 没毛病
AppConfig中存在@Configuration注解 只打印了一次"creating bean1" 是因为spring在执行BeanFactoryPostProcessor后置处理器时. 执行到了ConfigurationClassPostProcessor的postProcessBeanFactory方法, 此方法对所有的全注解类进行了CGLIB代理, 对方法进行了增强, 但此时只是将产生的cglib的class添加到了当前全配置类对应的beanDefinition的beanClass属性中(注意: 此时并没有产生bean, 只是改变了beanClass属性)

2.4 查看cglib代理类内容

2.4.1 设置指定属性, 将cglib代理类保存至指定地方

// 将整个工程中产生的cglib代理类全部存入g盘的cglib文件夹中
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "g://cglib");

2.4.2 运行项目并查看文件夹

spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第8张图片

2.4.3 将整个com文件夹copy至idea中可以解析class文件的目录下

  • 因spring源码是用gradle编译的, 我copy进的是out文件夹中, 若是普通的maven项目, 把它copy至target文件夹中即可
  • 生成的代理类文件夹结构如下:
    spring 5.0.x源码学习系列七: ConfigurationClassPostProcessor的身份二_第9张图片
  • 代理类源码:

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.eugene.sumarry.csdn.invokeBeanFactoryPostProcessor3;
    
    import java.lang.reflect.Method;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.cglib.core.ReflectUtils;
    import org.springframework.cglib.core.Signature;
    import org.springframework.cglib.proxy.Callback;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    import org.springframework.cglib.proxy.NoOp;
    import org.springframework.context.annotation.ConfigurationClassEnhancer.EnhancedConfiguration;
    
    /**
     * 它继承了AppConfig, 所以断定它就是AppConfig类的cglib代理类
     */
    public class AppConfig$$EnhancerBySpringCGLIB$$912e823e extends AppConfig implements EnhancedConfiguration {
        private boolean CGLIB$BOUND;
        public static Object CGLIB$FACTORY_DATA;
        private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
        private static final Callback[] CGLIB$STATIC_CALLBACKS;
        private MethodInterceptor CGLIB$CALLBACK_0;
        private MethodInterceptor CGLIB$CALLBACK_1;
        private NoOp CGLIB$CALLBACK_2;
        private static Object CGLIB$CALLBACK_FILTER;
        private static final Method CGLIB$bean1$0$Method;
        private static final MethodProxy CGLIB$bean1$0$Proxy;
        private static final Object[] CGLIB$emptyArgs;
        private static final Method CGLIB$bean2$1$Method;
        private static final MethodProxy CGLIB$bean2$1$Proxy;
        private static final Method CGLIB$setBeanFactory$6$Method;
        private static final MethodProxy CGLIB$setBeanFactory$6$Proxy;
        public BeanFactory $$beanFactory;
    
        static void CGLIB$STATICHOOK1() {
            CGLIB$THREAD_CALLBACKS = new ThreadLocal();
            CGLIB$emptyArgs = new Object[0];
            Class var0 = Class.forName("com.eugene.sumarry.csdn.invokeBeanFactoryPostProcessor3.AppConfig$$EnhancerBySpringCGLIB$$912e823e");
            Class var1;
            CGLIB$setBeanFactory$6$Method = ReflectUtils.findMethods(new String[]{"setBeanFactory", "(Lorg/springframework/beans/factory/BeanFactory;)V"}, (var1 = Class.forName("org.springframework.beans.factory.BeanFactoryAware")).getDeclaredMethods())[0];
            CGLIB$setBeanFactory$6$Proxy = MethodProxy.create(var1, var0, "(Lorg/springframework/beans/factory/BeanFactory;)V", "setBeanFactory", "CGLIB$setBeanFactory$6");
            Method[] var10000 = ReflectUtils.findMethods(new String[]{"bean1", "()Lcom/eugene/sumarry/csdn/invokeBeanFactoryPostProcessor3/Bean1;", "bean2", "()Lcom/eugene/sumarry/csdn/invokeBeanFactoryPostProcessor3/Bean2;"}, (var1 = Class.forName("com.eugene.sumarry.csdn.invokeBeanFactoryPostProcessor3.AppConfig")).getDeclaredMethods());
            CGLIB$bean1$0$Method = var10000[0];
            CGLIB$bean1$0$Proxy = MethodProxy.create(var1, var0, "()Lcom/eugene/sumarry/csdn/invokeBeanFactoryPostProcessor3/Bean1;", "bean1", "CGLIB$bean1$0");
            CGLIB$bean2$1$Method = var10000[1];
            CGLIB$bean2$1$Proxy = MethodProxy.create(var1, var0, "()Lcom/eugene/sumarry/csdn/invokeBeanFactoryPostProcessor3/Bean2;", "bean2", "CGLIB$bean2$1");
        }
    
        final Bean1 CGLIB$bean1$0() {
            return super.bean1();
        }
    
        /**
         * 代理增强的bean1方法
         */
        public final Bean1 bean1() {
            MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }
    
            return var10000 != null ? (Bean1)var10000.intercept(this, CGLIB$bean1$0$Method, CGLIB$emptyArgs, CGLIB$bean1$0$Proxy) : super.bean1();
        }
    
        final Bean2 CGLIB$bean2$1() {
            return super.bean2();
        }
    
        /**
         * 代理增强的bean2方法
         */
        public final Bean2 bean2() {
            // 这里获取到产生cglib代理类时的方法拦截器
            // 在spring中默认的方法拦截器有这三个:
            // private static final Callback[] CALLBACKS = new Callback[] {
            //            new BeanMethodInterceptor(),
            //            new BeanFactoryAwareMethodInterceptor(),
            //            NoOp.INSTANCE
            //    };
            // 方法拦截器的具体作用没有去研究, 这里大致走的是方法拦截器, 在方法拦截器中对bean2方法进行了增强
            MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_0;
            }
    
            return var10000 != null ? (Bean2)var10000.intercept(this, CGLIB$bean2$1$Method, CGLIB$emptyArgs, CGLIB$bean2$1$Proxy) : super.bean2();
        }
    
        final void CGLIB$setBeanFactory$6(BeanFactory var1) throws BeansException {
            super.setBeanFactory(var1);
        }
    
        public final void setBeanFactory(BeanFactory var1) throws BeansException {
            MethodInterceptor var10000 = this.CGLIB$CALLBACK_1;
            if (var10000 == null) {
                CGLIB$BIND_CALLBACKS(this);
                var10000 = this.CGLIB$CALLBACK_1;
            }
    
            if (var10000 != null) {
                var10000.intercept(this, CGLIB$setBeanFactory$6$Method, new Object[]{var1}, CGLIB$setBeanFactory$6$Proxy);
            } else {
                super.setBeanFactory(var1);
            }
        }
    
        public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
            String var10000 = var0.toString();
            switch(var10000.hashCode()) {
                case -1792804773:
                    if (var10000.equals("bean2()Lcom/eugene/sumarry/csdn/invokeBeanFactoryPostProcessor3/Bean2;")) {
                        return CGLIB$bean2$1$Proxy;
                    }
                    break;
                case 720662557:
                    if (var10000.equals("bean1()Lcom/eugene/sumarry/csdn/invokeBeanFactoryPostProcessor3/Bean1;")) {
                        return CGLIB$bean1$0$Proxy;
                    }
                    break;
                case 2095635076:
                    if (var10000.equals("setBeanFactory(Lorg/springframework/beans/factory/BeanFactory;)V")) {
                        return CGLIB$setBeanFactory$6$Proxy;
                    }
            }
    
            return null;
        }
    
        public AppConfig$$EnhancerBySpringCGLIB$$912e823e() {
            CGLIB$BIND_CALLBACKS(this);
        }
    
        public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
            CGLIB$THREAD_CALLBACKS.set(var0);
        }
    
        public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
            CGLIB$STATIC_CALLBACKS = var0;
        }
    
        private static final void CGLIB$BIND_CALLBACKS(Object var0) {
            AppConfig$$EnhancerBySpringCGLIB$$912e823e var1 = (AppConfig$$EnhancerBySpringCGLIB$$912e823e)var0;
            if (!var1.CGLIB$BOUND) {
                var1.CGLIB$BOUND = true;
                Object var10000 = CGLIB$THREAD_CALLBACKS.get();
                if (var10000 == null) {
                    var10000 = CGLIB$STATIC_CALLBACKS;
                    if (var10000 == null) {
                        return;
                    }
                }
    
                Callback[] var10001 = (Callback[])var10000;
                var1.CGLIB$CALLBACK_2 = (NoOp)((Callback[])var10000)[2];
                var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];
                var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
            }
    
        }
    
        static {
            CGLIB$STATICHOOK2();
            CGLIB$STATICHOOK1();
        }
    
        static void CGLIB$STATICHOOK2() {
        }
    }
    

三、总结

  • ConfigurationClassPostProcessorBeanFactoryPostProcessor身份最重要的就是为全注解类添加cglib代理了。当然除此之外, 还注册了一个类型为ImportAwareBeanPostProcessorBeanPostProcessor,这里还未总结到它有何用。
  • I am a slow walker, but I never walk backwards.
  • github spring源码学习地址: https://github.com/AvengerEug/spring/tree/develop/resourcecode-study

你可能感兴趣的:(javaspring)