@PostConstruct注解好多人以为是Spring提供的。其实是Java自己的注解。
Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。
通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
通过@PostConstruct注解能够通过一种更友好的方式将配置进行导入,代码如下:
/**
* 引导类
*/
@Configuration
public class BootstrapConsts {
@Value("${file.client.type}")
private String fileClientType;
@Value("${file.oss.endPoint}")
private String endPoint;
@Value("${file.oss.accessKeyId}")
private String accessKeyId;
@Value("${file.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${file.oss.bucketName}")
private String bucketName;
@Value("${file.oss.rootDir}")
private String rootDir;
/**
* 文件客户端类型
*/
public static String file_client_type;
/**
* OSS地址(不同服务器,地址不同)
*/
public static String end_point;
/**
* OSS键id(去OSS控制台获取)
*/
public static String access_key_id;
/**
* OSS秘钥(去OSS控制台获取)
*/
public static String access_key_secret;
/**
* OSS桶名称(这个是自己创建bucket时候的命名)
*/
public static String bucket_name;
/**
* OSS根目录
*/
public static String root_dir;
@PostConstruct
private void initial() {
file_client_type = fileClientType;
end_point = endPoint;
access_key_id = accessKeyId;
access_key_secret = accessKeySecret;
bucket_name = bucketName;
root_dir = rootDir;
}
}
写法有如下两种方式:
@PostConstruct
public void method(){}
public @PostConstruct void method(){}
被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的init()方法。被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。
服务器加载Servlet过程:
另外,spring中Constructor、@Autowired、@PostConstruct的顺序:
其实从依赖注入的字面意思就可以知道,要将对象B注入到对象A,那么首先就必须得生成对象A和对象B,才能执行注入。所以,如果一个类A中有个成员变量b被@Autowried注解,那么@Autowired注入是发生在A的构造方法执行完之后的。
如果想在生成对象时完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么久无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。
Constructor >> @Autowired >> @PostConstruct
@Component
public class A {
@Autowired
private B b;
public A() {
System.out.println("执行A的构造方法,此时b还未被注入: b = " + b);
}
@PostConstruct
private void init() {
System.out.println("@PostConstruct将在依赖注入完成后被自动调用: b = " + b);
}
}
@Component
public class B {
public B(){
System.out.println("执行B的构造方法");
}
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application-context.xml"})
public class MessageTest {
@Resource
A a;
@Test
public void testAB(){
}
}
执行testAB()方法结果:
执行A的构造方法,此时b还未被注入: b = null
执行B的构造方法
@PostConstruct将在依赖注入完成后被自动调用: b = com.nss.B@51841ac6
通过以上结果可以看出:被@PostConstruct注解的方法将在该类中所有注入操作完成之后执行。