1. 关于注解 PostConstruct 

public @interface PostConstruct

PostConstruct 注释用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化。
应用 PostConstruct 注释的方法必须遵守以下标准:

1)该方法不得有参数,除非是在 EJB 拦截器 (interceptor) 的情况下。
根据 EJB 规范的定义,在这种情况下它将带有一个 InvocationContext 对象 ;

2)该方法的返回类型必须为 void;

3)该方法不得抛出已检查异常;

4)应用 PostConstruct 的方法可以是 public、protected、package private 或 private;

5)除了应用程序客户端之外,该方法不能是 static;

6)该方法可以是 final;

7)如果该方法抛出未检查异常,那么不得将类放入服务中,除非是能够处理异常并可从中恢复的 EJB。

2.  @PostConstruct 和 @PreConstruct

从Java EE5规范开始,Servlet增加了两个影响Servlet生命周期的注解(Annotation):@PostConstruct和@PreConstruct。

这两个注解被用来修饰一个非静态的void()方法.  而且这个方法不能有抛出异常声明。

@PostContruct是spring框架的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。

 1)@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,且只会被服务器调用一次,类似于Serclet的inti()方法。   被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。

 2) @PreConstruct修饰的方法会在服务器卸载Servlet的时候运行,且只会被服务器调用一次,类似Servlet的destroy()方法。被@PreConstruct修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

 3)用法:

@PostConstruct

public void someMethod(){}

或者

public @PostConstruct void someMethod(){}

4)作用:

1.spring项目加载数据字典

 @PostConstruct 注解的方法在项目启动的时候执行这个方法,
 也可以理解为在spring容器启动的时候执行,
 可作为一些数据的常规化加载,比如数据字典之类的。

2.spring项目的定时任务

 spring 自带的 @schedule 无开关,项目启动总会启动一个线程;
 Java 的 timer 可设置开关,自由控制,关闭时不会启动线程;
 但 timer 也需要一个启动类,如放到main函数里启动,这样代码的耦合性高。 

综上:使用 PostConstruct  干净、方便。

3.  启动速度

 注解多少会影响服务器的启动速度。服务器在启动的时候,会遍历Web应用的WEB-INF/classes下的所有class文件与WEB-INF/lib下的所有jar文件,以检查哪些类使用了注解。如果程序中没有使用任何注解,可以在web.xml中设置<web-app>的metadatacomplete属性为true来关掉服务器启动时的例行检查。

4.  执行顺序

思路 1)

被@PostConstruct 修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。PreDestroy()方法在destroy()方法执行后执行。

spring PostConstruct未执行 spring postconstruct 顺序_spring 

执行顺序

另外,spring中Constructor、@Autowired、@PostConstruct的顺序

从依赖注入的字面意思可知,要将对象p注入到对象a,那么首先就必须得生成对象p与对象a,才能执行注入。所以,如果一个类A中有个成员变量p被@Autowired注解,那么@Autowired注入是发生在A的构造方法执行完之后的。

如果想在生成对象时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。

Constructor >> @Autowired >> @PostConstruct

思路 2)

从 jvm 类加载时机来看 

JVM 在加载阶段通过类的全路径找到该类并把类的信息加载到JVM的方法区,

--> 在堆区实例化有关 java.lang.Class 对象,作为方法区中这个类的信息的入口;

--> 在连接阶段,为类的静态变量 logClinet 分配内存并赋予 JVM 默认初始值 null;

因为注解@PostConstruct的缘故,在类初始化之前会先加载该使用该注解的方法,而后再执行类的初始化。

即加载顺序为:

    构造方法  ——> @Autowired —— > @PostConstruct ——> 静态方法