confused mind
confused mind

Reputation: 91

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...

Upvotes: 6

Views: 2950

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279960

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).

Upvotes: 5

Related Questions