我很想知道是否有一个接口可以告诉Spring启动一个特定的bean,调用它的初始化过程(通过afterPropertiesSet()作为InitializingBean,或者通过init-method,或者其他一些方式),然后扔掉它。
我的用例是一个简单的“健全性检查器”,它将在启动Web应用程序时检查数据库中的有效值。虽然我们的特定bean的开销很小,但在应用程序上下文中保持bean永远是没有意义的,因为一旦bean初始化,就不再需要它了。
我确信此类行为还有其他用例,但我还没有在Spring发现这样的事情。
特别是,我在Spring的Java变体中寻找它,我可以根据需要访问3.x及以上。
编辑:根据接受的答案,以下是提供解决方案的简单方法:
public final class NullReturningBeanPostProcessor implements BeanPostProcessor {
private List<String> beanNamesToDiscard = new ArrayList<String>();
/**
* Creates a new {@link NullReturningBeanPostProcessor} instance.
*/
public NullReturningBeanPostProcessor() {
super();
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanNamesToDiscard.contains(beanName)) {
return null;
}
return bean;
}
public void setBeanNamesToDiscard(List<String> beanNamesToDiscard) {
if (beanNamesToDiscard != null) {
this.beanNamesToDiscard = beanNamesToDiscard;
}
}
}
将此bean后处理器与适当的bean放在应用程序上下文中将使它们为空,并且在初始化之后有资格进行垃圾回收。遗憾的是,bean配置元数据仍将保留在应用程序上下文中。
答案 0 :(得分:6)
要实现这一点,我会将该bean实现BeanPostProcessor
然后:
@Override
Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean == this ? null : bean;
}
这应该导致ApplicationContext丢弃它,但只有在它执行了初始化步骤之后才会丢弃它。
请注意,您还需要实现postProcessBeforeInitialization()
,只需编写return bean;
。
更新:这不起作用。但不是由于MetroidFan2002的评论(见下文),而是由于JavaDoc的另一部分:
ApplicationContexts可以在其中自动检测BeanPostProcessor bean bean定义并将它们应用于随后创建的任何bean。
显然你不能将BeanPostProcessor应用于自身。 抱歉误报:)
答案 1 :(得分:1)
您可以使用MethodInvokingFactoryBean
bean定义在应用程序上下文初始化时执行方法。但是,如果在调用方法之前需要初始化某些bean,则必须小心依赖关系。在checkDatabase
,sanityChecker
和beanA
初始化之后,以下将对名为beanB
的bean执行beanC
方法:
<bean
id="methodInvoker"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
depends-on="beanA, beanB, beanC"
lazy-init="false"
p:singleton="false"
p:target-method="checkDatabase"
p:target-object-ref="sanityChecker"
/>
<bean
id="sanityChecker"
class="com.example.SanityChecker"
lazy-init="true"
scope="prototype"
/>
由于checkDatabase
是原型,因此其生命周期不受应用程序上下文管理,应在初始化后进行垃圾回收;这是单元测试可以证明的东西。 <{1}}可能还需要成为methodInvoker
垃圾收集的原型。
答案 2 :(得分:0)
如果您有另一个添加此职责的bean(例如,处理应用程序生命周期的现有bean),您可以使用该bean实现ApplicationListener<ContextRefreshedEvent>
并在那里进行健全性检查。否则我喜欢@Costi的答案。