共计 7125 个字符,预计需要花费 18 分钟才能阅读完成。
前言
- 上篇博客 spring 5.0.x 源码学习系列六: 后置处理器 ConfigurationClassPostProcessor 之 BeanDefinitionRegistryPostProcessor 身份次要介绍了 ConfigurationClassPostProcessor 的BeanDefinitionRegistryPostProcessor身份, 为了精通 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() {} }
三、总结
- ConfigurationClassPostProcessor之 BeanFactoryPostProcessor 身份最重要的就是为全注解类增加 cglib 代理了。当然除此之外, 还注册了一个类型为 ImportAwareBeanPostProcessor 的BeanPostProcessor,这里还未总结到它有何用。
- I am a slow walker, but I never walk backwards.
- github spring 源码学习地址: https://github.com/AvengerEug/spring/tree/develop/resourcecode-study
正文完