我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求。这时候可以考虑在bean被加载时执行一些方法;经验优先想到了二种方法;
方法一 init方法方法bean对象初始化时实现方法
方法二 实现InitializingBean
InitalizingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。
那么二种方法都是在bean对象被初始化的时候执行的先后顺序如何呢
话不多说上代码
@Configuration
public class EatFactory implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("开启after方法");
}
@Bean(initMethod = "initmethod")
public void print(){
System.out.println("初始化方法");
}
}
执行结果
那么为什么是这种结果呢 我们查看下源碼AbstractAutowireCapableBeanFactory 的 invokeInitmethods方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//判断bean是否继承InitializingBean 如果继承执行要执行afterpro*pertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
//如果RootBeanDefinition 不为空,bean的class不为空执行下面的方法
if (mbd != null && bean.getClass() != NullBean.class) {
//获取初始化方法的名称执行initmethod方法
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
解释RootBeanDefiniiton 存储bean的信息,class对象,注解,构造函数之类的继承了AbstractBeanDefinition有兴趣的同学可以看下,
所以从上面看我们知道bean对象加载时先执行afterPropertiesSet 在执行initmethods