需求:在tomcat服务启动时初始化一些参数。
想法:容器启动时执行方法,最容易想到的就是servlet中可以配置load-on-startup,设置一个正整数也就可以随容器一起启动。
解决方案:Spring提供了当一个Bean初始化后执行方法的扩展点:InitializingBean。这里的初始化指的就是当该Bean的属性被注入完成后(注意:这里并不是所有属性都需要被设置),所以InitializingBean接口提供的方法名称也很形象:afterPropertiesSet()。
@Component
public class InitServlet implements InitializingBean {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void afterPropertiesSet() throws Exception {
//在这里面进行操作
}
}
另外还有两种方法也可以实现如上的功能。
若采用XML来配置Bean的话,可以指定属性init-method
通过注解@PostConstruct来修改初始化方法
这里我们举例说明一下@PostConstruct在代码中的用法
@Service("AjaxCacheableService")
public class AjaxCacheableService{
/**
* 构造方法执行后,初始化,
*/
@PostConstruct
public void init() {
//代码写在这里
}
}
Spring中调用Bean的初始化代码的源代码:
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();// 这里触发afterPropertiesSet
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();<span style="white-space:pre"> </span>// 这里触发afterPropertiesSet
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();// 这里是触发init-method
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
从这里可以看出,三者可以同时存在,触发的顺序是先触发@PostConstruct修饰的方法,再触发afterPropertiesSet(),最后触发init-method
其中@PostConstruct是通过注册一个BeanPostProcessor,在Bean的初始化方法之前调用,而afterPropertiesSet()和init-method都在初始化方法中调用。