I am studying for the Spring Core certification an I have some doubts about how Spring handle the beans lifecycle and in particular about the bean post processor.
So I have this schema:
It is pretty clear for me what it means:
The following steps take place in the Load Bean Definitions phase:
The @Configuration classes are processed and/or @Components are scanned for and/or XML files are parsed.
Bean definitions added to BeanFactory (each indexed under its id)
Special BeanFactoryPostProcessor beans invoked, it can modify the definition of any bean (for example for the property-placeholder values replacements).
Then the following steps take place in the beans creation phase:
Each bean is eagerly instantiated by default (created in right order with its dependencies injected).
After dependency injection each bean goes through a post-processing phase in which further configuration and initialization may occur.
After post processing the bean is fully initialized and ready for use (tracked by its id until the context is destroyed)
Ok, this is pretty clear for me and I also know that there are two types of bean post processors which are:
Initializers: Initialize the bean if instructed (i.e. @PostConstruct).
and All the rest: that allow for additional configuration and that may run before or after the initialize step
And I post this slide:
So it is very clear for me what does the initializers bean post processors (they are the methods annotated with @PostContruct annotation and that are automatically called immediately after the setter methods (so after the dependency injection), and I know that I can use to perform some initialization batch (as populate a cache as in the previous example).
But what exactly represents the other bean post processor? What do we mean when we say that these steps are performed before or after the initialization phase?
So my beans are instantiated and its dependencies are injected, so then the initialization phase is completed (by the execution of a @PostContruct annotated method). What do we mean by saying that a Bean Post Processor is used before the initialization phase? It means that it happens before the @PostContruct annotated method execution? Does it means that it could happen before the dependency injection (before that the setter methods are called)?
And what exactly do we mean when we say that it is performed after the initialization step. It means that it happens after that the execution of a @PostContruct annotated method, or what?
I can easily figure into my head why I need a @PostContruct annotated method but I can't figure some typical example of the other kind of bean post processor, can you show me some typical example of when are used?
Spring's BeanPostProcessor gives us hooks into the Spring bean lifecycle to modify its configuration. BeanPostProcessor allows for direct modification of the beans themselves.
Inside Spring, a bean exploits the Inversion of Control feature by which an object defines its dependencies without creating them. This object delegates the job of constructing and instantiating such dependencies to an IoC container, the Spring lightweight container.
BeanPostProcessor is interface that tells Spring to do some processing after initialization some beans. BeanPostProcessor is interface that tells Spring to do some processing after initialization some beans. This allows you to add some custom logic before and after spring bean creation.
After loading the bean definitions from all styles of configurations, BeanFactoryPostProcessor comes into the picture to modify the definition of some beans, and then the container instantiates the beans. Finally, BeanPostProcessor works on the beans, and it can modify and change the bean object.
Spring doc explains the BPPs under Customizing beans using BeanPostProcessor. BPP beans are a special kind of beans that get created before any other beans and interact with newly created beans. With this construct, Spring gives you means to hook-up to and customize the lifecycle behavior simply by implementing a BeanPostProcessor
yourself.
Having a custom BPP like
public class CustomBeanPostProcessor implements BeanPostProcessor { public CustomBeanPostProcessor() { System.out.println("0. Spring calls constructor"); } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(bean.getClass() + " " + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(bean.getClass() + " " + beanName); return bean; } }
would be called and print out the class and bean name for every created bean.
To undersand how the method fit the bean's lifecycle, and when exactly the method's get called check the docs
postProcessBeforeInitialization(Object bean, String beanName) Apply this BeanPostProcessor to the given new bean instance before any bean initialization callbacks (like InitializingBean's afterPropertiesSet or a custom init-method).
postProcessAfterInitialization(Object bean, String beanName) Apply this BeanPostProcessor to the given new bean instance after any bean initialization callbacks (like InitializingBean's afterPropertiesSet or a custom init-method).
The important bit is also that
The bean will already be populated with property values.
For what concerns the relation with the @PostConstruct
note that this annotation is a convenient way of declaring a postProcessAfterInitialization
method, and Spring becomes aware of it when you either by registerCommonAnnotationBeanPostProcessor
or specify the <context:annotation-config />
in bean configuration file. Whether the @PostConstruct
method will execute before or after any other postProcessAfterInitialization
depends on the order
property
You can configure multiple BeanPostProcessor instances, and you can control the order in which these BeanPostProcessors execute by setting the order property.
The typical example for a bean post processor is when you want to wrap the original bean in a proxy instance, e.g. when using the @Transactional
annotation.
The bean post processor will be handed the original instance of the bean, it may call any methods on the target, but it also gets to return the actual bean instance that should be bound in the application context, which means that it can actually return any object it wants. The typical scenario when this is useful is when the bean post processor wraps the target in a proxy instance. All invocations on the bean bound in application context will pass through the proxy, and the proxy then gets to perform some magic before and/or after invocations on the target bean, e.g. AOP or transaction management.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With