排查问题原因
如下代码所示,我想要载构造函数里面使用@Value注解配置的demo.name
但是发现一直是null
@Service
public class DemoService {
@Value("demo.name")
public String name;
public DemoService() {
System.out.println("name = " + name);
}
}
原来这跟Bean生命周期有关系
Bean创建时先创建一个对象:一般调用无参构造函数new一个对象,也就是上述代码的new DemoService()
然后再填充属性。
Bean生命周期如下
1、实例化Bean对象,调用构造函数,此时属性一般都为null
2、设置对象属性
3、检查Aware相关接口,如BeanNameAware#setBeanName
,BeanFactoryAware#setBeanFactory
4、BeanPostProcessor#postProceBeforeInitialization
方法前置处理
5、调用InitializingBean#afterPropertiesSet
方法
6、调用bean
的init-method
7、BeanPostProcessor#postProcessAfterInitialization
后置处理
8、注册必要的Destruction相关回调接口
9、使用Bean
10、是否实现DisposableBean
接口,如果实现则调用他的destory
接口
11、调用bean
的destroy-method
下面提供2种方式来解决问题:
1、使用构造函数解决问题
2、使用@PostConstruct注解解决问题
使用构造函数解决问题
理解问题之后我们就可以解决问题了,下面是一种解决方案,在构造函数之前传参数之前进行注入
@Service
public class DemoService implements BeanNameAware, BeanFactoryAware, InitializingBean {
@Value("demo.name")
public String name;
public DemoService(@Value("demo.name") String name) {
System.out.println("name = " + name);
}
}
使用@PostConstruct注解解决问题
上述代码为null的问题,可以使用@PostConstruct
注解修改为如下
@Service
public class DemoService {
@Value("demo.name")
public String name;
public DemoService() {
}
@PostConstruct
public void init() {
System.out.println("name = " + name);
}
}
@PostConstruct 执行时机
1 、@PostConstruct
注解在BeanNameAware#setBeanName
,BeanFactoryAware#setBeanFactory
执行完毕之后执行。
2、@PostConstruct
注解在(BeanPostProcessor#postProcessAfterInitialization
)之前开始执行
使用@PostConstruct
注意事项:
1、只有一个非静态方法能使用此注解
2、被注解的方法不得有任何参数
3、被注解的方法返回值必须为void
4、被注解方法不得抛出已检查异常
5、此方法只会被执行一次