preface

When we talked about Spring’s Lifecycle, we mentioned that Spring’s Lifecycle interface can be used to implement some of the Spring container Lifecycle logic. In contrast, @postconstruct and @PreDestroy perform operations on Bean initialization or destruction.

Obviously Spring’s Lifecycle deals with logic based on the Lifecycle of the container, whereas @PostConstruct and @PreDestroy deal with business logic based on the Lifecycle of the Bean.

Many people here have the misconception that the @PostConstruct annotation is also provided by Spring. It’s not. It’s a Java built-in annotation. Let’s start with the @PostConstruct annotation.

JSR – 250 specification

Before we get to the @Postconstruct annotation, let’s introduce a concept: the JSR-250 specification.

Jsr-250 predefined annotations around the use of “resources,” which can be interpreted as an instance of a Class Class, a JavaBean, or aBean in Spring.

JSR – 250 annotations associated all in javax.mail. The annotation and javax.mail annotation. The security package, including: resource definitions and access control. Annotations such as @resource, @postconstruct, @predestroy, @generated, etc. are all defined in this specification.

The specification does not provide a specific implementation, but only guidance documentation and a few comments, to be implemented by a specific framework.

That is, the @PostConstruct annotation is not provided by Spring, but Spring implements the @PostConstruct convention according to the JSR-250 specification. Other frameworks, or you can write your own, can also be implemented by convention.

@ PostConstruct conventions

@PostConstruct and @PreDestroy were introduced in Java EE 5 under the Javax. Annotation package, which is the annotations defined by the Java Extension package. Where the x in Javax stands for extension. Java’s original designers decided that these features were not core Java apis, so they were included in extensions that could be implemented by convention.

Here’s a quick look at the comments on this class:

The PostConstruct annotation is used to perform any initialization on methods that need to be performed after dependency injection is complete. This method must be called before the class is put into the service. All classes that support dependency injection must support this annotation. Methods annotated with PostConstruct must be called even if the class does not request any resources to be injected. There is only one way to comment with this annotation.”

“Methods that apply PostConstruct annotations must comply with all of the following criteria:

  • This method must not take any arguments, except in the case of an EJB interceptor, which will take an InvocationContext object;
  • The return type of this method must be void;
  • This method must not throw checked exceptions;
  • PostConstruct can be public, protected, Package Private or private.
  • This method cannot be static except for the application client;
  • The method can be final;
  • If this method throws an unchecked exception, the class cannot be put into the service unless it is an EJB that can handle the exception and recover from it.

In addition to the above conventions, there are certain processing opportunities if used in a Servlet container.

The execution timing of @postconstruct

The timing of @PostConstruct execution described below is based on Spring’s implementation. Methods decorated with @postconstruct run when the server loads the Servlet and are executed only once. PostConstruct is executed after the constructor and before the init() method.

The corresponding flow chart is as follows:

Examples demonstrate

Now that you understand the basic concepts above, let’s take a look at an example that is very simple to use.

Add the following classes to the Java 8-based Spring Boot project:

@service public class OrderService {public OrderService(){system.out.println ("OrderService constructor is executed..." ); } @postConstruct private void init() {system.out.println ("PostConstruct annotation method called "); } @predestroy private void shutdown() {system.out.println ("PreDestroy method is called "); }}Copy the code

When the Spring Boot project is started, the console prints the following log:

The OrderService constructor is executed... The PostConstruct annotation method is calledCopy the code

When the service is shut down, it prints:

The PreDestroy annotation method is calledCopy the code

Through the example, the above theory is proved basically.

Future removal of Java9

In Java 8 we could have used the corresponding annotations directly, but by Java 9 and later, J2EE deprecated the @PostConstruct and @Predestroy annotations and planned to remove them in Java 11.

We have two solutions to this situation: first, add additional dependencies; Second, try something else.

The first scenario is if you insist on using the annotations, or if your project cannot get rid of them for the time being. Well, you can add dependencies manually:

< < the dependency > < groupId > javax.mail. An annotation/groupId > < artifactId > javax.mail. The annotation - API < / artifactId > < version > 1.3.2 < / version > </dependency>Copy the code

That is, they can be removed, but you can still add their dependencies. As a cautionary note, try not to use these annotations in projects; Java 11 plans to remove them.

At this point, if you are using a Spring project, consider another way to do the same thing, based on Spring’s InitializingBean and DisposableBean interfaces:

@Service public class PaymentService implements InitializingBean, DisposableBean {public PaymentService(){system.out.println ("PaymentService constructor executed..." ); Override public void destroy() throws Exception {system.out.println ("destroy method is called "); } @override public void afterPropertiesSet() throws Exception {system.out.println ("afterPropertiesSet method is called "); }}Copy the code

Start the project and print the following log:

The PaymentService constructor is executed... The afterPropertiesSet method is calledCopy the code

Stop the project and print the following information:

The destroy method is calledCopy the code

That said, in the Spring ecosystem, we already have an alternative, and one that is recommended.

In fact, Spring does not abide by the convention

In the convention above we said that “only one method can be annotated with this annotation”. Try adding an @postConstruct annotation to OrderService:

@service public class OrderService {public OrderService(){system.out.println ("OrderService constructor is executed..." ); } @postConstruct private void init() {system.out.println ("PostConstruct annotation method called "); } @postconstruct private void init1() {system.out.println ("PostConstruct init1 annotation method called "); } @predestroy private void shutdown() {system.out.println ("PreDestroy method is called "); }}Copy the code

Start the program and print the log:

The OrderService constructor is executed... PostConstruct init1 annotation method is called PostConstruct annotation method is calledCopy the code

Not only are no errors reported, but both methods are executed. What does that mean? This goes to show that conventions are sometimes made to be broken, just remember this one special case.

Implementation principles of Spring

Above is a brief introduction to @Postconstruct. Below is a brief analysis of the implementation principle from the Spring source code level.

Let’s start with a Spring interface called BeanPostProcessor:

Public interface BeanPostProcessor {// Any Bean instantiation, And Bean has populated (fill attribute) will callback the method Object postProcessBeforeInitialization (Object Bean, String beanName) throws BeansException; // Any Bean instantiation, And Bean has populated (fill attribute) will callback the method Object postProcessAfterInitialization (Object Bean, String beanName) throws BeansException;Copy the code

The BeanPostProcessor is an extended interface provided to us by the Spring IOC container with two callback methods. After a BeanPostProcessor implementation class is registered with the Spring IOC container, for each bean instance created by the Spring IOC container, before the initialization methods (such as afterPropertiesSet and any declared init methods) are called, Will call the BeanPostProcessor postProcessBeforeInitialization method, and at the completion of a bean instance initialization method calls, Will call the BeanPostProcessor postProcessAfterInitialization method, the calling sequence can be simple schematic is as follows:

-- > Spring IOC container instantiation Bean > call BeanPostProcessor postProcessBeforeInitialization method -- - > call the Bean instance initialization method -- -- > Call the BeanPostProcessor postProcessAfterInitialization methodCopy the code

A implementation class and BeanPostProcessor CommonAnnotationBeanPostProcessor, is specialized in processing @ PostConstruct and @ PreDestroy annotation. One in the superclass InitDestroyAnnotationBeanPostProcessor CommonAnnotationBeanPostProcessor, corresponding invocation logic is as follows:

InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization() InitDestroyAnnotationBeanPostProcessor. FindLifecycleMetadata metadata () / / assembly life cycle InitDestroyAnnotationBeanPostProcessor. BuildLifecycleMetadata ()/comments/find @ PostConstruct method InitDestroyAnnotationBeanPostProcessor. InitAnnotationType/comments/find @ PreDestroy method InitDestroyAnnotationBeanPostProcessor. DestroyAnnotationType / / reflection to invoke the metadata. InvokeInitMethods (bean, beanName);Copy the code

The details of the business logic are not shown here, but you can trace the source code if you are interested.

summary

A few things to note in this article: First, Spring simply implements the Java specification for the @PostConstruct annotation; Second, this annotation is deprecated in Java 9 and is no longer recommended. Third, Spring’s InitializingBean and DisposableBean can be used to replace the corresponding functions.

About the blogger: Author of the technology book SpringBoot Inside Technology, loves to delve into technology and writes technical articles.

Public account: “program new vision”, the blogger’s public account, welcome to follow ~

Technical exchange: Please contact the weibo user at Zhuan2quan