• 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 注解的。

  • 相关阅读:
    asp.net售后维修管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
    easyscholar配置秘钥连接Zotero-style,更方便的了解文献!
    《生命·觉者》蔡志忠:一个人,活出自己是最重要的
    将自定义 GitHub 徽章添加到您的代码库
    java基于ssm+jsp的高校失物招领系统 (代码+数据库+LW+调试)
    vue element-table分页回显选中与再次更改保留状态,前端手动过滤多条件查询
    web:[ACTF2020 新生赛]Include
    Java学习Day031(异常)
    go开发之个人微信的开发
    什么是 游戏引擎 ?各个主流引擎的区别
  • 原文地址:https://blog.csdn.net/qiaohao0206/article/details/125875899