I'm learning spring and I'm stuck with the bean lifecycle!
When creating a bean, Spring provides several ways to interact with it. We can use one or more of the following:
BeanFactoryPostProcessor
BeanPostProcessor#postProcessBeforeInitialization
@PostConstruct
InitializingBean#afterPropertiesSet
@Bean#initMethod
BeanPostProcessor#postProcessAfterInitialization
Spring calls them in the order above
My question is: Why all these points of interaction? and when to use each of them (the use case)?
A BeanFactoryPostProcessor
and a BeanPostProcessor
are quite different beast and also apply to different things.
A BeanFactoryPostProcessor
will operate on the metadata for a bean (I like to call it the recipe) and will post process that. A well know example is the PropertySourcesPlaceholderConfigurer
which will inject/replace all @Value
in configuration with the value. A BeanFactoryPostProcessor
operates on the metadata and thus before any bean has been created.
The BeanPostProcessor
can be applied to a bean and can even replace a bean. Spring AOP uses this quite a lot. An example is the PersistenceExceptionTranslationPostProcessor
, when a bean has been created it will pass through this BeanPostProcessor
and when it is annotated with @Persistence
the bean will be replaced by a proxy. This proxy adds exception translation (i.e. it will convert JpaException
and SQLException
to the Spring DataAccessException
). This is done in a BeanPostProcessor. And can be be done before the init-callbacks are called (the
postProcessBeforeInitializationor after they have been called the
postProcessAfterInitialization). The
PersistenceExceptionTranslationPostProcessorwill run in the
postProcessAfterInitialization` as it needs to be certain the bean has been initialized.
The ServletContextAwareProcessor
will run right after the object has been created to inject the ServletContext
as early as possible as the initializing of a bean might depend on it.
The 3 callbacks for initializing a bean are more or less the same but are called in sequence because they have been included in later versions. It starter with only an interface InitializingBean
and init-method
in xml (later also added to @Bean
and the annotation support was added when annotations became a thing.
You need init methods to initialize a bean, you might want to check if all properties have been set (like a required datasource) or you might want to start something. A DataSource
(especially a connection pool) is a good example to initialize. After all dependencies have been injected you want to start the pool so it will open the connections. Now as you probably cannot modify the code you want to use the init-method
if you control the code you probably want to add @PostConstruct
. If you are writing an framework that depends on Spring I would use the InitializingBean
.
Next to those 3 init methods you also have the destruction counter-parts. The DisposableBean
interface (and destroy-method
) and the @PreDestroy
annotation. Again when you stop your application you also want to close the connections in your connection pool and you want to probably call the close
method on the DataSource
. A perfect sample of a destruction callback.