Is there a way to tell Spring that you should use a bean during initialization and then discard immediately?

I am interested in knowing if there is an interface that I can use to tell Spring to launch a particular bean up, call its initialization procedure (either as an InitializingBean via afterPropertiesSet (), or via the init method or in some other way), and then throw it away.

My use case is a simple health checker that checks the database for valid values ​​at startup for a web application. Although the overhead would be small for our particular bean, considering that a bean for eternity in the application context is pointless, once the bean is initialized, it is no longer needed.

I'm sure there are other use cases for this type of behavior, but I haven't found anything like it in Spring yet.

In particular, I am looking for it in the Java version of Spring, I have access to 3.x and as needed.

EDIT: based on the accepted answer, the following is a simple hack to provide a solution:

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; } } } 

Placing the bean mail processor with the appropriate beans for reset in the application context will make them empty and will have the right to garbage collection after they are initialized. The bean configuration metadata, unfortunately, will still remain in the application context.

+7
source share
3 answers

To achieve this, I would make a bean implementation of BeanPostProcessor , and then:

 @Override Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean == this ? null : bean; } 

This should cause the ApplicationContext to cancel it, but only after it has completed the initialization steps.

Note that you also need to implement postProcessBeforeInitialization() and just write return bean; .


Update: this does NOT work. But not because of the MetroidFan2002 comment (see below), but because of another part of the JavaDoc:

ApplicationContexts can automatically detect BeanPostProcessor beans in its beans and apply them to any beans created subsequently.

Thus, it is obvious that you cannot apply BeanPostProcessor to yourself. Sorry for the false signal :)

+6
source

You can use the definition of the MethodInvokingFactoryBean bean to execute the method when initializing the application context. Although you need to be careful with dependencies if some beans need to be initialized before the method is called. The following would checkDatabase method on a bean named sanityChecker after initializing beanA , beanB and 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" /> 

Since checkDatabase is a prototype, its life cycle is not controlled by the application context and must be garbage collected after initialization; something unit test may turn out to be. methodInvoker can also be a prototype for checkDatabase for garbage collection.

+1
source

If you have another bean to which it makes sense to add this responsibility (for example, an existing bean related to the application life cycle), you can implement the ApplicationListener<ContextRefreshedEvent> bean and perform a health check there, Otherwise I like @Costi's answer .

0
source

All Articles