【发布时间】:2019-03-13 22:07:02
【问题描述】:
实现BeanPostProcessor接口与在Spring中使用XML配置文件中的init/destroy方法属性或实现InitializingBean/DisposableBean接口有什么区别?
【问题讨论】:
标签: spring
实现BeanPostProcessor接口与在Spring中使用XML配置文件中的init/destroy方法属性或实现InitializingBean/DisposableBean接口有什么区别?
【问题讨论】:
标签: spring
这在 Spring 文档中关于Container Extension Points 的解释非常清楚。
BeanPostProcessor 接口定义了回调方法,你可以 实施以提供您自己的(或覆盖容器的默认值) 实例化逻辑、依赖解析逻辑等等。如果你 想在Spring容器之后实现一些自定义逻辑 完成实例化、配置和初始化 bean,您可以 插入一个或多个 BeanPostProcessor 实现。
所以本质上定义在 BeanPostProcessor 中的方法 postProcessBeforeInitialization 在 bean 初始化之前被调用(如名称所示),同样postProcessAfterInitialization 在 bean 初始化之后被调用。
与@PostConstruct、InitializingBean 和自定义init 方法的区别在于它们是在bean 本身上定义的。它们的顺序可以在 spring 文档的Combining lifecycle mechanisms 部分找到。
所以基本上 BeanPostProcessor 可用于为多个 bean 执行自定义实例化逻辑,而其他 bean 是基于每个 bean 定义的。
【讨论】:
以上答案清楚地解释了一些非常重要的方面。
除此之外,理解 beanPostProcessor 和 init 和 destroy 方法也是 Spring bean 生命周期的一部分也很重要。
BeanPostProcessor 类有两个方法。
1) postProcessBeforeInitialization - 顾名思义,它用于确保在初始化之前采取必要的操作。例如您想从远程源/服务加载某些属性文件/读取数据。
2) postProcessAfterInitialization - 在将 bean 引用提供给应用程序之前,您在初始化之后想要做的任何事情。
被质疑的方法在生命周期中的顺序如下:
1) BeanPostProcessor.postProcessBeforeInitialization()
2) 初始化()
3) BeanPostProcessor.postProcessAfterInitialization()
4) 销毁()
您可以通过编写具有 sysout 的简单示例并检查它们的顺序来检查这一点。
【讨论】:
Init 和 Destroy 回调方法是 Spring bean 生命周期阶段的一部分。 init 方法将在 bean 实例化之后执行。同样,destroy 方法将在 bean 终结之前执行。
我们可以使用实现接口InitializingBean和DisposableBean,或者使用注解@postconstruct和@predestroy来实现这个功能,或者用init-method和destroy-method属性声明<bean>。
BeanPostProcessor 接口用于扩展框架的功能,如果想通过spring容器进行任何配置前和后bean初始化。
例如:默认情况下,Spring 不会意识到 @PostConstruct 和 @PreDestroy 注释。要启用它,我们必须注册 CommonAnnotationBeanPostProcessor 或在 bean 配置文件中指定 <context:annotation-config />。这里CommonAnnotationBeanPostProcessor 是为注释预定义的BeanPostProcessor 实现。喜欢:
@Required 启用RequiredAnnotationBeanPostProcessor 处理工具
@Autowired 启用AutowiredAnnotationBeanPostProcessor 处理工具
【讨论】:
另外一个主要的区别是 InitializingBean,DisposableBean 相关的 afterPropertiesSet() 和 destory() 方法不接受任何参数并且返回类型也是 void,所以我们没有实现任何自定义逻辑。 但是来到 BeanPostProcess 方法 postProcessBeforeInitialization(Object bean,String beanName) 和 postProcessAfterInitialization(Object bean,String beanName) 接受这两个参数并且返回类型也是 Object 所以我们能够编写初始化逻辑以及任何基于传递的自定义登录豆子……
这两个回调方法特征都包含了bean的生命周期,下面是生命周期如下
1) BeanPostProcessor.postProcessBeforeInitilazation()
2) @postConstruct 或 InitializingBean.afterPropertiesSet() 或初始化方法是
如果三种方式可用,则在 xml /* 中定义也遵循相同的 oredr **/
3) BeanPostProcessor.postProcessAfterInitialization()
4) @preDestroy 或 DisposibleBean.destroy() 或在 xml 中定义的销毁方法 /* 如果有三种方法可用,这里也遵循相同的 oredr **/
【讨论】:
只是对上述所有答案的简短补充:如果您有任何通用逻辑,需要普遍应用于所有 Spring bean 的通用逻辑,例如向 bean 注入记录器,设置属性文件,通过反射为你的bean的字段设置默认值;您可以将该逻辑放在一个地方:@Overriden 回调(例如:postProcessBeforeInitialization(Object arg0, String arg1),如果您正在实现 BeanPostProcessor 接口);而不是在所有 bean 中复制相同的逻辑。
【讨论】:
a) postProcessBeforeInitialization() 将在 bean 初始化之前被调用。
b)一旦 bean 被初始化,不同的回调方法将按照 Spring 文档按以下顺序调用:
主要区别在于,以上3个方法是在初始化完成后调用的,都是通过postProcessBeforeInitialization()方法完成的。
一旦这些方法完成,方法 postProcessAfterInitialization() 将被调用,然后以相同的顺序调用销毁方法:
使用@PreDestroy 注释的方法
由 DisposableBean 回调接口定义的destroy()
通过 XML 定义的destroy() 方法。
【讨论】: