有没有办法指定Spring在初始化时应该使用bean然后立即丢弃?

时间:2011-06-16 17:32:30

标签: java spring

我很想知道是否有一个接口可以告诉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配置元数据仍将保留在应用程序上下文中。

3 个答案:

答案 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,则必须小心依赖关系。在checkDatabasesanityCheckerbeanA初始化之后,以下将对名为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的答案。