Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostConstruct getting called before BeanPostProcessor

I am currently new to spring. I was trying to follow the order in which PostConstruct and BeanPostProcessor are called.

According to what I have learned the below is the order :-

  1. BPP -> postProcessBeforeInitialization
  2. PostContruct
  3. BPP -> postProcessAfterInitialization

However I see the below order being followed:-

  1. PostContruct
  2. BPP -> postProcessBeforeInitialization
  3. PostContruct
  4. BPP -> postProcessAfterInitialization

SpringConfig file foo.xml Removed the beans tag context:component-scan base-package="springtest"

@Component
public class MySpring implements ApplicationContextAware,BeanPostProcessor{

public static int temp =0;

public MySpring(){
    System.out.println("Initializing MySpring Constructor");
}

@PostConstruct
public void temp(){
    System.out.println("PostConsturct" + this.getClass());
    temp++;
}

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("Before BPP " + bean.getClass());

    return this;
}

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("After BPP " + bean.getClass());

    return this;
}

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    System.out.println("Initializing ApplicationContext");

}}

Response

  1. Initializing MySpring Constructor
  2. Initializing ApplicationContext
  3. PostConsturctclass springtest.MySpring
  4. After Properties set class springtest.MySpring
  5. Before BPP class org.springframework.context.event.EventListenerMethodProcessor
  6. PostConsturctclass springtest.MySpring
  7. After Properties set class springtest.MySpring
  8. After BPP class springtest.MySpring
  9. Before BPP class org.springframework.context.event.DefaultEventListenerFactory
  10. PostConsturctclass springtest.MySpring
  11. After Properties set class springtest.MySpring
  12. After BPP class springtest.MySpring

MySpring.temp value is 3 means PostContruct was calles 3 times.

Could someone please help me in the above...

like image 265
confused mind Avatar asked Jan 01 '16 14:01

confused mind


1 Answers

It's getting called three times because you're replacing every bean with your MySpring bean.

Your method

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("Before BPP " + bean.getClass());

    return this;
}

is returning this, effectively saying that the bean object you're currently post processing should be replaced by the MySpring object. You can verify this by attempting to get any other bean from your ApplicationContext.

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigurationBean.class);
ctx.getBean(ConfigurationBean.class);

This will fail with a NoSuchBeanDefinitionException.

Your post-processing methods should be returning the value of their bean parameter.

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("Before BPP " + bean.getClass());

    return bean;
}

@PostConstruct invocation is implemented with its own BeanPostProcessor, CommonAnnotationBeanPostProcessor. Registered BeanPostProcessor instances are used in order.

When your ApplicationContext initializes your MySpring instance, the CommonAnnotationBeanPostProcessor is already initialized and therefore processes your bean. After MySpring is completely initialized, Spring detects that it is a BeanPostProcessor and registers it as well. It is registers it before that CommonAnnotationBeanPostProcessor (there's a priority setting for BeanPostProcessor instances).

like image 88
Sotirios Delimanolis Avatar answered Sep 29 '22 06:09

Sotirios Delimanolis