Bean初始化完成后如何调用方法?


237

我有一个用例,需要在ApplicationContext加载一次时在Bean中一次调用一个(非静态)方法。如果我为此使用MethodInvokingFactoryBean可以吗?还是我们有更好的解决方案?

附带说明,我使用ConfigContextLoaderListener在Web应用程序中加载应用程序上下文。并且想要,如果实例化了bean'A',则只需调用一次methodA()。

如何做到这一点呢?

Answers:


196

您可以使用类似:

<beans>
    <bean id="myBean" class="..." init-method="init"/>
</beans>

实例化bean时,它将调用“ init”方法。


15
但是,在大多数情况下,postConstruct应该会更好,因为我们不想弄乱spring bean的初始化。
lwpro2

4
@ lwpro2这里的“不想弄乱Spring bean的初始化”是什么意思?
Yngve Sneen Lindal 2014年

@Mercer Traieste我应该在这里为class属性提供什么?我可以在这里给控制器课吗?
KJEjava48 '16

314

以其他答案扩展@PostConstruct的建议,我认为这确实是最好的解决方案。

  • 它使您的代码与Spring API分离(@PostConstruct位于javax。*中)
  • 它显式地将您的init方法注释为需要初始化Bean的东西
  • 您无需记住将init-method属性添加到Spring bean定义中,spring会自动调用该方法(假设您在上下文中的其他任何地方注册了注解配置选项)。

9
谢谢,这有效。请注意,如果要与Spring一起使用,则必须包括“ <context:annotation-config />”以注册CommonAnnotationBeanPostProcessor bean(如上所述)
khylo 2011年

2
一个合适的方法<context:component-scan>也可以工作,并且如果您在类路径上有很大的非Spring库,则可以减少启动时间。
Donal Fellows,

5
用于PostConstruct的JavaDoc表示每个类只能使用一种方法进行注释:docs.oracle.com/javaee/5/api/javax/annotation/…–
Andrew Swan

@PostConstruct不适用于交易经理,请参阅:forum.spring.io/forum/spring-projects/data/…–
mmm

2
当您要实例化的bean不是您自己的类而是某个第三方类时,@ PostConstruct也不会给您太大用
John Rix 2015年

102

参考文献中所述,可以考虑三种不同的方法

使用init-method属性

优点:

  • 不需要bean来实现接口。

缺点:

  • 构造后无需立即指示需要使用此方法来确保正确配置Bean。

实现InitializingBean

优点:

  • 无需指定初始化方法,也无需打开组件扫描/注释处理。
  • 适用于库附带的bean,我们不希望使用该库的应用程序关注bean的生命周期。

缺点:

  • 比init-method方法更具侵入性。

使用JSR-250 @PostConstruct lifecyle注释

优点:

  • 在使用组件扫描自动检测bean时很有用。
  • 明确指出将使用一种特定的方法进行初始化。意图更接近代码。

缺点:

  • 初始化不再在配置中集中指定。
  • 您必须记住要打开注释处理(有时可能会忘记它)

4
我认为@PostConstruct准确地使用它实际上是一件好事,因为它是类的一部分,需要在初始化处理结束时调用方法。
Donal Fellows,

如果该类确实需要它,而您不能在构造函数中使用它,那么我认为它是代码气味。
user482745

39

您是否尝试实施InitializingBean?听起来完全像您在追求什么。

缺点是您的bean可以识别Spring,但在大多数应用程序中还不错。


2
您是否有选择在XML中指定初始化方法而不选择实现接口的原因?
标记

4
多数民众赞成在一个味道。该接口是Spring组件模型的一部分,并且仅用于该目的,而对于自定义命名方法而言,为完成组件生命周期而必须调用它可能并不是很明显。因此,这主要为通信服务。当然存在引入对Spring框架的依赖的缺点。介于两者之间的一种好方法是@PostConstruct的用法,因为它具有清晰的语义但没有引入依赖关系……
Oliver Drotbohm 09年

7
Oliver给了我一些很好的借口,但实际上我只是忘记了init方法:)另一个原因是,类型本身知道在设置完所有属性之后就需要“完成”了—这不是从根本上说,应该在配置中。
乔恩·斯基特

8

您可以在应用程序上下文中部署自定义BeanPostProcessor来实现。或者,如果您不介意在bean中实现Spring接口,则可以使用InitializingBean接口或“ init-method”指令(相同的链接)。


有谁知道如何编写BeanPostProcessor的详细信息。听起来正是我所需要的。干杯:)
peakit

Spring提供了许多示例。只需查看BeanPostProcessor的JavaDoc API,您将找到许多实现类的链接。然后查看它们的源代码。
罗布H

-7

为了进一步消除对这两种方法的混淆,即使用

  1. @PostConstruct
  2. init-method="init"

根据个人经验,我意识到使用(1)仅在servlet容器中有效,而(2)在任何环境中均有效,即使在桌面应用程序中也是如此。因此,如果要在独立应用程序中使用Spring,则必须使用(2)来执行“初始化后调用此方法”。


4
从技术上讲,@PostConstruct(在基于Spring的应用程序中使用时)与拥有的Spring上下文的寿命相关。这样的上下文可以在各种应用程序中使用。
Donal Fellows,

那是我所期望的行为,但对我没有用。
阿约林德(Ayorinde)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.