After Properties Set and init-method, @PostConstruct of Spring Initializing Bean

Explain:
Bean s in Spring containers have a life cycle. Spring allows specific operations to be performed after initialization and before beans are destroyed. There are three common settings:
By implementing the InitializingBean/Disposable Bean interface, we customize the operation methods after initialization/before destruction.
The init-method/destroy-method attribute of the element specifies the operation method invoked after initialization/before destruction.
Add @PostConstruct or @PreDestroy annotations to the specified method to determine whether the method is invoked after initialization or before destruction.
That's why we have a question. Are these three ways exactly the same, first and second?

With this question in mind, we will try to find the answer by testing the code and analyzing the Spring source code.
First, let's write a simple test code:

public class InitSequenceBean implements InitializingBean {  

    public InitSequenceBean() {  
       System.out.println("InitSequenceBean: constructor");  
    }  

    @PostConstruct  
    public void postConstruct() {  
       System.out.println("InitSequenceBean: postConstruct");  
    }  

    public void initMethod() {  
       System.out.println("InitSequenceBean: init-method");  
    }  

    @Override  
    public void afterPropertiesSet() throws Exception {  
       System.out.println("InitSequenceBean: afterPropertiesSet");  
    }  
}  

And add the following Bean definitions in the configuration file:

<bean class="InitSequenceBean" init-method="initMethod"></bean>

Okay, let's start the Spring container and watch the output to see the order of the three.

InitSequenceBean: constructor
InitSequenceBean: postConstruct
InitSequenceBean: afterPropertiesSet
InitSequenceBean: init-method

Through the above output results, the sequence of the three is clear at a glance.

Constructor > @PostConstruct > InitializingBean > init-method

Let's start with a general analysis of why these results occur: Constructor is called first, no doubt. Initializing Bean precedes init-method, which we can understand (discussed in the life cycle of Spring container), but why does PostConstruct precede Initializing Bean?

Once again, let's look at Spring source code with this question.

Through Debug and looking at the call stack, we found this class, org. spring framework. context. annotation. Common Annotation BeanPostProcessor, which gives us some information by name -- a BeanPostProcessor. What comes to mind? In discussing the life cycle of Spring containers, we mentioned that BeanPostProcessor's postProcess BeforeInitialization was invoked before afterProperties Set and init-method in the Bean life cycle.

Look again at the CommonAnnotationBeanPostProcessor class, which inherits from InitDestroy AnnotationBeanPostProcessor. Init Destroy Annotation Bean Post Processor, as its name implies, is a pre/post processor made when a bean is initialized and destroyed.

By looking at the postProcessBeforeInitialization method under the InitDestroyAnnotationBeanPostProcessor class:

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
       LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());  
       try {  
           metadata.invokeInitMethods(bean, beanName);  
       }  
       catch (InvocationTargetException ex) {  
           throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());  
       }  
       catch (Throwable ex) {  
           throw new BeanCreationException(beanName, "Couldn't invoke init method", ex);  
       }  
        return bean;  
    }  

Look at the findLifecycle Metadata method, and then we trace it to the build Lifecycle Metadata method body. Look at the content of the build Lifecycle Metadata method body:

private LifecycleMetadata buildLifecycleMetadata(final Class clazz) {  
       final LifecycleMetadata newMetadata = new LifecycleMetadata();  
       final boolean debug = logger.isDebugEnabled();  
       ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {  
           public void doWith(Method method) {  
              if (initAnnotationType != null) {  
                  if (method.getAnnotation(initAnnotationType) != null) {  
                     newMetadata.addInitMethod(method);  
                     if (debug) {  
                         logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);  
                     }  
                  }  
              }  
              if (destroyAnnotationType != null) {  
                  if (method.getAnnotation(destroyAnnotationType) != null) {  
                     newMetadata.addDestroyMethod(method);  
                     if (debug) {  
                         logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);  
                     }  
                  }  
              }  
           }  
       });  
       return newMetadata;  
}  

Analysis of this code reveals that it is here to determine whether a method has been annotated by initAnnotationType/destroyAnnotationType, and if so, it is added to the init/destroy queue and executed one by one.

What is the initAnnotationType/destroyAnnotationType annotation? We see the following code in the constructor of CommonAnnotationBeanPostProcessor:

public CommonAnnotationBeanPostProcessor() {  
       setOrder(Ordered.LOWEST_PRECEDENCE - 3);  
       setInitAnnotationType(PostConstruct.class);  
       setDestroyAnnotationType(PreDestroy.class);  
       ignoreResourceType("javax.xml.ws.WebServiceContext");  
}  

Everything is clear. In short, the @PostConstruct annotated method is executed in the BeanPostProcessor pre-processor, so of course it is executed before InitializingBean and init-method.

Finally, the conclusion of this paper is given. Bean in the process of instantiation:

Constructor > @PostConstruct > InitializingBean > init-method

Download the source code of this article: https://lb-multi-demo.googlecode.com/svn/trunk/spring-lifecycle-test

Tags: Spring Attribute svn xml

Posted on Thu, 27 Dec 2018 15:03:06 -0500 by schlag