I think spring-framework 6.0.7 does not fully conform to the contract defined by the jakarta.annotation.PostConstruct
annotation (from jakarta.annotation-api-2.1.1.jar).
The Javadoc of the annotation says: "Only one method in a given class can be annotated with this annotation.".
However, it is possible to annotate at least two methods of a given class which is registered as a @Component
or @Bean
with this annotation and all annotated methods are executed after the bean is initialized after calling SpringApplication.run()
.
Shouldn't the Spring application refuse to initialize such a bean if it finds more than one method annotated with @PostConstruct
(although this would restrict developers to only having one @PostConstruct
method per bean class)?
This is my POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.tutego</groupId>
<artifactId>date4u</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>date4u</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.shell</groupId>
<artifactId>spring-shell-starter</artifactId>
<version>3.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
This is my bean class:
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;
@Component
public class MyComponent {
@PostConstruct
void postConstruct1() {
System.out.println("post construct1");
}
@PostConstruct
void postConstruct2() {
System.out.println("post construct2");
}
}
And my application class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Date4uApplication {
public static void main(String[] args) {
SpringApplication.run(Date4uApplication.class, args);
}
}
Comment From: sbrannen
Hi @Tibotanum,
Thanks for raising the issue.
Shouldn't the Spring application refuse to initialize such a bean if it finds more than one method annotated with
@PostConstruct
(although this would restrict developers to only having one@PostConstruct
method per bean class)?
Not only would that be restrictive, it would be a breaking change for applications which rely on the existing behavior.
In addition, our annotation-based init/destroy method infrastructure supports not only @PostConstruct
and @PreDestroy
but rather any custom init/destroy annotations, and the same semantics are applied to all such annotations.
In light of that, we do not plan to introduce any limitations on such annotation usage that are specific to one particular specification.
Comment From: Tibotanum
Hi @sbrannen, Many thanks for the clarification!