InitializingBean
是Spring中一个接口、就单单一个待实现的方法
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
例子
public class TestConfig implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("bean初始化!!!");
}
}
applicatio.xml
<?xml version="1.0" encoding="UTF8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="testConfig" class="com.wei.config.TestConfig"/>
</beans>
Test.java
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
}
}
输出结果
执行大概流程
可以看到ClassPathXmlApplicationContext
构造
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
具体方法流程、对应的是方法中的方法、一个个点使用Ctrl+鼠标左键点击
点进去就能看到具体实现流程、或碰到接口方法时使用Ctrl+alt+b
进入到该接口方法具体的方法实现中
refresh()->
finishBeanFactoryInitialization(beanFactory)->
getBean(weaverAwareName)->
getBeanFactory().getBean(name)->
doGetBean(name, null, null, false)->
createBean(beanName, mbd, args)->
doCreateBean(beanName, mbdToUse, args)->
initializeBean(beanName, exposedObject, mbd)->
invokeInitMethods(beanName, wrappedBean, mbd)->
((InitializingBean) bean).afterPropertiesSet();
最后在AbstractAutowireCapableBeanFactory
类中invokeInitMethods()
方法中调用了重写的afterPropertiesSet()
方法!
protected void invokeInitMethods(String beanName, final Object bean,
@Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
// 使用了Spring Security就走这边
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 这就是调用afterPropertiesSet()方法
((InitializingBean) bean).afterPropertiesSet();
}
}
// 这块地方就是在bean中配置了init-method并指定类中的方法就会执行指定的方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 调用指定的初始化方法、是通过反射的方式调用指定的方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
如
<bean id="testConfig" class="com.wei.config.TestConfig" init-method="testInit"/>
TestConfig.java
public class TestConfig implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("bean初始化!!!");
}
public void testInit(){
System.out.println("b--***********************");
}
}
输出结果
如果bean
不是单例的情况下初始方法会执行多遍
可以执行初始方法的几种方式
-
实现
InitializingBean
接口重写afterPropertiesSet()
方法 -
在bean中指定销毁方法
-
<bean id="testConfig" class="com.wei.config.TestConfig" init-method="cs" />
-
-
或使用注解Bean的方式、使用
ClassPathXmlApplicationContext
是加载是创建不出来的bean的、要使用AnnotationConfigApplicationContext
加载这个配置类-
@Bean(initMethod = "xx")
注意的就是bean必须是单例的、否则初始方法被使用时都会执行一遍
-
-
或者使用
@PostConstruct
标记一个方法为初始化方法、会在上面两种方法之前执行、在InitDestroyAnnotationBeanPostProcessor
类中postProcessBeforeInitialization()
方法中metadata.invokeInitMethods(bean, beanName);
方法通过反射调用注解标注的方法!