前言

  • 上篇博客spring 5.0.x源码学习系列六: 后置处理器ConfigurationClassPostProcessor之BeanDefinitionRegistryPostProcessor身份次要介绍了ConfigurationClassPostProcessorBeanDefinitionRegistryPostProcessor身份, 为了精通spring, 咱们还须要对它的第二个身份BeanFactoryPostProcessor进行总结

一、ConfigurationClassPostProcessor之BeanFactoryPostProcessor身份

  • 它的这个身份同样起到了十分重要的作用: 为全配置类增加cglib代理,避免以@Bean的形式创立bean时呈现反复调用雷同逻辑的问题。 接下来咱们依照如下demo一起探索它。

二、我的项目demo

2.1 我的项目全景图

2.1.1 AppConfig

2.1.2 Bean1

2.1.3 Bean2

2.1.4 Entry

2.2 运行后果

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

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

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 运行我的项目并查看文件夹

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

  • 因spring源码是用gradle编译的, 我copy进的是out文件夹中, 若是一般的maven我的项目, 把它copy至target文件夹中即可
  • 生成的代理类文件夹构造如下:
  • 代理类源码:

    //// 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