1.简介
@PostConstruct是java5的时候引入的注解,主要用于标记一个方法,表示该方法应在依赖注入完成后自动调用。通常在使用Java EE或者Spring框架时使用这个注解,以便在Bean初始化之后执行一些初始化工作, 可作为一些数据的常规化加载,比如数据字典之类的。
1.1 @PostConstruct注解修饰的方法运行说明
- 1)当一个class被注解为一个Bean,那么class上被@PostConstruct注解的方法将会在会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。
- 2)这个并不是因为servlet加载而执行啊,只是一种JSR-250的规范,当bean创建完成的时候,会后置执行@PostConstruct修饰的方法啊。
备注: 关于@PostConstruct修饰的方法的运行,笔者在网上看到了两种不同的声音,一种说是在服务器加载Servlet的时候运行,另一种说是一种JSR-250的规范。能力有限暂时无法辨别,还望大佬指点。
2.API说明(以java8为例)
PostConstruct注解用于需要在依赖项注入完成后执行的方法上,以执行任何初始化。必须在类投入服务之前调用此方法。所有支持依赖项注入的类都必须支持此注解。即使类没有请求注入任何资源,也必须调用带有PostConstruct注解的方法。只有一个方法可以用这个注解。应用PostConstruct注释的方法必须满足以下所有条件:
- 1). 该方法不能有任何参数,除非在拦截器的情况下,在这种情况下,它接受拦截器规范定义的InvocationContext对象。
- 2). 定义在拦截器类上的方法必须具有以下特征之一:
注意:PostConstruct拦截器方法不能抛出应用程序异常,但如果同一个拦截器方法在生命周期事件之外还插入业务方法或超时方法,则可以声明它抛出受检查异常,包括java.lang.Exception。如果PostConstruct拦截器方法返回一个值,则该值将被容器忽略。 - 3). 在非拦截器类上定义的方法必须具有以下特征:
- 4). 应用PostConstruct的方法可以是公共的、受保护的、包私有的或私有的。
- 5). 除了应用程序客户端之外,该方法绝对不能是静态的。
- 6). 方法可以被final修饰。
- 7). 如果该方法抛出未经检查的异常,则该类不能投入服务,可以处理异常甚至从异常中恢复的EJB除外。
2.1 特点
- 1)只有一个非静态方法能使用此注解。(因为spring没严格按照Java规范来,经过实测,在同一个类中可以有多个非静态方法可以使用此注解,不过实际项目中很少出现单个类多个@PostConstruct)
- 2)被注解的方法不得有任何参数。
- 3)被注解的方法返回值必须为void。
- 4)此方法只会被执行一次
3. 执行顺序
在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
4. java9及后续版本中的替代方案
J2EE已在Java 9中弃用 @PostConstruct ,并计划在Java 11中将其删除。替代方案通过实现 InitializingBean 接口实现或@Bean注解中的initMethod属性。
- 1). InitializingBean 接口:
import org.springframework.beans.factory.InitializingBean;
@Configuration
public class MyBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
// Initialization code here
}
}
- 2). @Bean注解中的initMethod属性
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean(initMethod = "init")
public MyBean myBean() {
return new MyBean();
}
}
public class MyBean {
public void init() {
// Initialization code here
}
}
如果你还是非要在Java 9 及以后的版本使用 @PostConstruct,你也可以手动添加相关依赖。
maven:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>