1. Introduction

Spring allows us to attach custom actions to bean creation and destruction. We can, for example, do it by implementing the InitializingBean and DisposableBean interfaces.

In this quick tutorial, we’ll look at a second possibility, the @PostConstruct and @PreDestroy annotations.

进一步阅读:

Spring构造函数依赖注入

现代软件设计中最重要的开发原则之一就是依赖注入(Dependency Injection, DI),它自然而然地源于另一个关键原则:模块化。

Spring @ComponentScan - 过滤器类型

In an earlier tutorial, we learned about the basics of Spring component scans.

Spring中使用Lombok的构造函数注入

Lombok 是一个非常有用的库,用于简化样板代码。如果您还不熟悉它,强烈建议您先阅读之前的教程——Lombok 入门教程。

2. @PostConstruct

Spring calls the methods annotated with @PostConstruct only once, just after the initialization of bean properties. Keep in mind that these methods will run even if there’s nothing to initialize.

The method annotated with @PostConstruct can have any access level, but it can’t be static.

One possible use of @PostConstruct is populating a database. For instance, during development, we might want to create some default users:

@Component
public class DbInit {

    @Autowired
    private UserRepository userRepository;

    @PostConstruct
    private void postConstruct() {
        User admin = new User("admin", "admin password");
        User normalUser = new User("user", "user password");
        userRepository.save(admin, normalUser);
    }
}

The above example will first initialize UserRepository and then run the @PostConstruct method.

3. @PreDestroy

A method annotated with @PreDestroy runs only once, just before Spring removes our bean from the application context.

Same as with @PostConstruct, the methods annotated with @PreDestroy can have any access level, but can’t be static.

@Component
public class UserRepository {

    private DbConnection dbConnection;
    @PreDestroy
    public void preDestroy() {
        dbConnection.close();
    }
}

The purpose of this method should be to release resources or perform other cleanup tasks, such as closing a database connection, before the bean gets destroyed.

4. javax.annotation or jakarta.annotation

From JDK 6 to JDK 8, the @PostConstruct and @PreDestroy annotations were part of the standard Java libraries under the javax.annotation package. However, with JDK 9, the entire javax.annotation package was removed from the core Java modules and fully eliminated in JDK 11. In Jakarta EE 9, this package has been relocated to jakarta.annotation.

So, sometimes, we may ask, “Should I use the annotations from javax.annotation or jakarta annotation?” This depends on the Spring version we use. To quickly understand the compatibilities among Spring, JDK, javax, and jakarta namespaces, let’s summarize them in a table:

Spring Version

JDK Version

Java / Jakatar Namespace

6.1.x

JDK 17 to JDK 23

jakarta

6.0.x

JDK 17 to JDK 21

jakarta

5.3.x

JDK 8 to JDK 21

javax

As the table above shows, with Spring 6.0.x and 6.1.x, we should use the jakarta namespace. However, if our project uses Spring 5.3.x and JDK 9 or a later version, since Spring 5.3.x only supports the javax namespace, we must explicitly add the javax.annotation-api dependency to our project:

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

The above XML shows an example of adding the javax.annotation-api dependency to a Maven project’s pom.xml.

5. Conclusion

In this brief article, we learned how to use the @PostConstruct and @PreDestroy annotations.

As always, all the source code is available over on GitHub.