• Spring - IoC 容器之拓展点 BeanPostProcessor


    概述

    Spring - IoC 容器之 Bean 的生命周期 这篇文章中,我们了解了 SpringBean 的生命周期,我们知道底层是通过回调实现的。同时对于其他情况的回调,Spring 官方文档 中有介绍,BeanPostProcessor 接口中定义了回调方法,我们可以实现这些方法来提供自己的实例化逻辑、依赖处理逻辑等。如果我们想要在 Spring IoC 容器 完成 Bean实例化配置初始化 之后实现一些自定义的逻辑,可以定义一个或多个自定义的 BeanPostProcessor 实现。

    同时,如果我们配置了多个 BeanPostProcessor 实例,我们可以通过实现 Ordered 接口设置 order 属性来控制这些实例的运行顺序。

    public interface BeanPostProcessor {
    
    	@Nullable
    	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    
    	@Nullable
    	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		return bean;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    举例

    首先定义一个 BeanPostProcessor 的实现类:

    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessBeforeInitialization..." + beanName + ":" + bean);
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessAfterInitialization..." + beanName + ":" + bean);
            return bean;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    @Component
    public class Cat implements InitializingBean, DisposableBean {
    
        @Override
        public void destroy() throws Exception {
            System.out.println("cat destroy...");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("cat afterPropertiesSet...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    创建 IoC 容器后,输出结果:

    // 配置类初始化前调用
    postProcessBeforeInitialization...mainConfigOfLifeCycle:com.keke.config.MainConfigOfLifeCycle$$EnhancerBySpringCGLIB$$661f10cf@4b213651
    // 配置类初始化之后调用
    postProcessAfterInitialization...mainConfigOfLifeCycle:com.keke.config.MainConfigOfLifeCycle$$EnhancerBySpringCGLIB$$661f10cf@4b213651
    // Bean 初始化调用之前
    postProcessBeforeInitialization...com.keke.bean.Cat:com.keke.bean.Cat@4241e0f4
    // Bean 初始化
    cat afterPropertiesSet...
    // Bean 初始化调用之后
    postProcessAfterInitialization...com.keke.bean.Cat:com.keke.bean.Cat@4241e0f4
    // 容器关闭,Bean 销毁
    cat destroy...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    原理

    上面的 org.springframework.beans.factory.config.BeanPostProcessor 接口,定义了两个默认方法,postProcessBeforeInitialization 方法在 InitializingBean.afterPropertiesSet()自定义的 init 方法 等初始化方法之前执行,postProcessAfterInitialization 在之后执行。

    ApplicationContext 会自动检测实现了 BeanPostProcessor 接口的实现类,并在 Bean 创建过程中调用这些 BeanPostProcessor,当然,这些实现了 BeanPostProcessor 接口的实现类需要作为 Bean 注册到 IoC 容器 中。

    在这里插入图片描述

    AbstractAutowireCapableBeanFactorydoCreateBean 方法中执行了创建 Bean 的过程:

    在这里插入图片描述

    在核心方法 initializeBean 方法中执行了初始化 Bean 的操作:

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    	...
    
    	Object wrappedBean = bean;
    	if (mbd == null || !mbd.isSynthetic()) {
    		// 执行所有 BeanPostProcessor 实现类的 postProcessBeforeInitialization 方法
    		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    	}
    
    	try {
    		// 调用初始化方法
    		invokeInitMethods(beanName, wrappedBean, mbd);
    	}
    	catch (Throwable ex) {
    		throw new BeanCreationException(
    				(mbd != null ? mbd.getResourceDescription() : null),
    				beanName, "Invocation of init method failed", ex);
    	}
    	if (mbd == null || !mbd.isSynthetic()) {
    		// 执行所有 BeanPostProcessor 实现类的 postProcessAfterInitialization 方法
    		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    	}
    
    	return wrappedBean;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    总结

    Spring 底层,大量使用了 BeanPostProcessor 来进行 Bean 的初始化前后的操作,我们查看 BeanPostProcessor 的常见实现类:

    在这里插入图片描述

    InitDestroyAnnotationBeanPostProcessor 就是用来处理 @PostConstruct@PreDestroy 注解的。AutowiredAnnotationBeanPostProcessor 是用来处理 @Autowired 注解的。

  • 相关阅读:
    maui BlazorWebView+本地html (vue、uniapp等都可以) 接入微信sdk 开发 Android app
    YBTOJ 树形dp合集
    pg和oracle的区别
    【数据结构(邓俊辉)学习笔记】向量02——动态空间管理
    JS数据类型 和 转换
    高通量筛选——离子化合物
    ModuleNotFoundError: No module named ‘xxx‘
    【新知实验室--音视频通话】腾讯云TRTC-实时音视频---多人会议视频通话SDK基础搭建
    测试路由器
    基于R语言分位数回归丨线性回归假设与分位数函数、线性分位数回归 、贝叶斯分位数回归、超越线性分位数回归等
  • 原文地址:https://blog.csdn.net/qiaohao0206/article/details/125875899