如何记忆 Spring Bean 的生命周期
执行顺序:Constructor > @PostConstruct > InitializingBean > init-method
实现InitializingBean接口,重写afterPropertiesSet方法
使用@PostConstruct注解
javaEE5引入了@PostConstruct和@PreDestroy两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作
@PostConstruct是Java自己的注解
@PostConstruct该注解被用来修饰一个非静态的void()方法
@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次
@PostConstruct在构造函数之后执行,init()方法之前执行
假设类UserController有个成员变量UserService被**@Autowired**修饰,那么UserService的注入是在UserController的构造方法之后执行的。如果想在UserController对象生成时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入的对象,那么就无法在构造函数中实现(ps:spring启动时初始化异常),例如:
@Component
public class UserController {
@Autowired
private UserService userService;
public UserController() {
// 调用userService的自定义初始化方法,此时userService为null,报错
userService.userServiceInit();
}
}
可以使用@PostConstruct
注解来完成初始化,@PostConstruct
注解的方法将会在UserService注入完成后被自动调用。
@Component
public class UserController {
@Autowired
private UserService userService;
public UserController() {
}
// 初始化方法
@PostConstruct
public void init(){
userService.userServiceInit();
}
}
**总结:**类初始化调用顺序:构造方法Constructor
> @Autowired
> @PostConstruct
InitializingBean是Spring提供的拓展性接口,InitializingBean接口为bean提供了属性初始化后的处理方法,它只有一个afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。
除了采用注解完成初始化,也可以通过实现InitializingBean完成类的初始化
@Component
public class UserController {
public UserController() {
}
// 初始化方法
@PostConstruct
public void init(){
userService.userServiceInit();
}
}
比较常见的如SqlSessionFactoryBean
,它就是通过实现InitializingBean
完成初始化的。
@Override
public void afterPropertiesSet() throws Exception {
// buildSqlSessionFactory()是完成初始化的核心方法,必须在构造方法调用后执行
this.sqlSessionFactory = buildSqlSessionFactory();
}
initMethod属性通过bean标签中的initMethod来配置实例化之后的初始化方法的
@Component
public class UserController {
public UserController() {
}
public void init(){
userService.userServiceInit();
}
// 初始化指向init()方法
@Bean(initMethod = "init")
public UserController test() {
return new UserController();
}
}
通过启动日志我们可以看出执行顺序优先级:构造方法 > postConstruct >afterPropertiesSet > init方法
public class MyInitializingBean implements InitializingBean {
public MyInitializingBean() {
System.out.println("我是MyInitializingBean构造方法执行...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("我是afterPropertiesSet方法执行...");
}
@PostConstruct
public void postConstruct() {
System.out.println("我是postConstruct方法执行...");
}
public void init(){
System.out.println("我是init方法执行...");
}
}
@Configuration
class config{
@Bean(initMethod = "init")
public MyInitializingBean test() {
return new MyInitializingBean();
}
}
//==================执行结果===================
/**
我是MyInitializingBean构造方法执行...
我是postConstruct方法执行...
我是afterPropertiesSet方法执行...
我是init方法执行...
*/
Spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中通过init-method指定,两种方式可以同时使用。
实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率要高一点,但是init-method方式消除了对spring的依赖。
如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。