Spring IOC源码分析三:Spring refresh下
文章目录
7.initMessageSource
在Spring容器中初始化一些国际化相关的属性。
8.initApplicationEventMulticaster
在Spring容器中初始化事件广播器,事件广播器用于事件的发布。
9.onRefresh
一个模板方法,不同的Spring容器做不同的事情。
比如web程序的容器AnnotationConfigEmbeddedWebApplicationContext中会调用createEmbeddedServletContainer方法去创建内置的Servlet容器。
10.registerListeners
把Spring容器内的时间监听器和BeanFactory中的时间监听器都添加的事件广播器中。
11.finishBeanFactoryInitialization
实例化BeanFactory中已经被注册但是未实例化的所有非懒加载实例
主流程
主流程大致为,从缓存中找到是否已经实例化了该 singleton bean,如果已经实例化好了,那么就直接返回;如果在缓存中没有找到,则将当前的 bean 封装为 RootBeanDefinition,然后通过调用 DefaultSingletonBeanRegistry#getSingleton 得到初始化好的 singleton bean,然后将其注册至缓存,然后再判断是普通 bean 还是 factory bean 作必要的处理后,最后返回。
AbstractBeanFactory#doGetBean
Object sharedInstance = getSingleton(beanName);
先从缓存中查找是否以及实例化了该bean,如果已存在,直接返回。
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
将当前bean标记为已创建。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//回调AbstractAutowireCapableBeanFactory 的 createBean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
这里调用DefaultSingletonBeanRegistry#getSingleton:
beforeSingletonCreation(beanName);
singletonObject = singletonFactory.getObject();
afterSingletonCreation(beanName);
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
beforeSingletonCreation和afterSingletonCreation 检查了当前bean是不是在被排除的bean集合中以及是不是正在创建。
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
而addSingleton是将实例化好的bean加入缓存
接下来重点关注singletonObject = singletonFactory.getObject(),这里回调了getObject方法,即AbstractAutowireCapableBeanFactory#createBean。通过此回调方法正式拉开了实例化 bean 的序幕。
AbstractAutowireCapableBeanFactory#createBean
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
在进行真正的实例化之前,会先调用一部分已注册的beanPostProcessor的before,after方法。
AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
可以看出,这里只处理实现了InstantiationAwareBeanPostProcessor的processor,如CommonAnnotationBeanPostProcessor,处理通用的注解,如Resource等。
从主流程可以看出主要做了三件事:一、create Bean Instance;二、populate bean;三、initialize bean。
create Bean Instance
createBeanInstance根据 bean 的不同配置方式,实现了三种实例化bean的方式,分别是 factory instantiate bean、autwire instantiate bean 以及 default instantiate bean。
AbstractAutowireCapableBeanFactory#createBeanInstance
instantiateUsingFactoryMethod(beanName, mbd, args);
autowireConstructor(beanName, mbd, ctors, null);
instantiateBean(beanName, mbd);
factory instantiate bean
ConstructorResolver#instantiate
this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args)
SimpleInstantiationStrategy#instantiate
Object result = factoryMethod.invoke(factoryBean, args);
if (result == null) {
result = new NullBean();
}
return result;
通过反射调用FactoryMethod实例化bean
autwire instantiate bean
ConstructorResolver#instantiate
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor constructorToUse, Object[] argsToUse) {
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
return BeanUtils.instantiateClass(ctor, args);
}
}
SimpleInstantiationStrategy#instantiate
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
return BeanUtils.instantiateClass(ctor, args);
}
//instantiateClass
ctor.newInstance(args);
//newInstance
T inst = (T) ca.newInstance(initargs);
这里也是通过使用其构造函数 constructor 使用Java 反射实例化了 bean。
default instantiate bean
AbstractAutowireCapableBeanFactory#instantiateBean
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
SimpleInstantiationStrategy#instantiate
BeanUtils.instantiateClass(constructorToUse);
//instantiateClass
ctor.newInstance(args);
//newInstance
T inst = (T) ca.newInstance(initargs);
这里仅仅是通过使用其构造函数 constructor 使用Java 反射实例化了 bean,并没有对其进行任何的参数赋值
populate bean
AbstractAutowireCapableBeanFactory#populateBean
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
进行依赖注入的过程,先处理autowire的注入,可以根据Bean的名字或类型来完成Bean的autowire
if (pvs != null) {
//对属性进行注入 例如feign
applyPropertyValues(beanName, mbd, bw, pvs);
}
然后对属性进行注入。通过这一步,将相关的 property populate 给 bean 以后,才算 bean 的实例化完成。
initialize bean
AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
invokeAwareMethods(beanName, bean); ①
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行bean-post-processor 的beforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization (wrappedBean, beanName);②
}
try {
//处理实现了InitializingBean接口的beans的回调方法
invokeInitMethods(beanName, wrappedBean, mbd);③
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//执行bean-post-processor 的afterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);④
}
return wrappedBean;
}
整个流程可以理解为三大块
- 注入 Aware 对象,见①;
- 调用 bean-post-processors 接口方法,见②和④;
- 调用 InitializingBean 方法,见③。
注入 Aware 对象
AbstractAutowireCapableBeanFactory#invokeAwareMethods
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
//将当前的beanFactory注入,这也就是为什么如果实现了BeanFactoryAware接口,会自动获取到但钱的BeanFactory实例
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
可以看到,注入了三种情况
- 如果当前 bean 实现了 BeanNameAware 接口,只是调用了 setBeanName,比如logging
- 如果当前 bean 实现了 BeanClassLoaderAware 接口,将 Spring 容器的 BeanClassLoader 注入到当前 bean
- 如果当前 bean 实现了 BeanFactoryAware 接口,将 Spring 容器中与 bean 初始化相关的 BeanFactory 实例注册给当前的 bean。
调用 bean-post-processors 接口方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
可以看出如果某个 beanProcessor 处理返回一个 null 则直接返回,并且终止其余的 bean-post-processors。要注意的是,该回调方法是针对对容器中所有的普通 bean 进行的回调。并且该方法是在回调 InitializeBean 接口方法之前调用,并且是在 populate bean之后进行的调用,通常是对原有 bean 做一层封装,然后返回该封装对象。这点BeanPostProcessor接口注释也已经说明。
public interface BeanPostProcessor {
/**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding {@code bean instanceof FactoryBean} checks.
* <p>This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other BeanPostProcessor callbacks.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
调用 InitializingBean 方法
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 + "'");
}
.....
((InitializingBean) bean).afterPropertiesSet();
.....
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
可以看到,主要回调的是InitializingBean接口的afterPropertiesSet方法,所以,我们可以让某个 bean 实现 InitializingBean 接口,并通过该接口实现一些当 bean 实例化好以后的回调方法,注意afterPropertiesSet并不返回任何值,所以,这里不是像 bean-post-processor 那样对 bean 起到修饰的作用,而是起到纯粹的调用作用
12.finishRefresh
refresh做完之后需要做的其他事情。
- 清除上下文级资源缓存(例如来自扫描的ASM元数据)。
- 初始化生命周期处理器,并设置到Spring容器中(LifecycleProcessor)
- 调用生命周期处理器的onRefresh方法,这个方法会找出Spring容器中实现了SmartLifecycle接口的类并进行start方法的调用
- 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作
- 发布EmbeddedServletContainerInitializedEvent事件告知对应的ApplicationListener进行响应的操作
- 调用LiveBeansView的registerApplicationContext方法:如果设置了JMX相关的属性,则就调用该方法
扩展
到这里Spring 容器的bean初始化就全部完成了,最后补充一个扩展,那就是ApplicationContext是在什么时候注入的,从上述文章不难看出,invokeAwareMethods并没有对ApplicationContext注入,经过测试发现,如果实现了ApplicationContextAware,则将会在调用 bean-post-processors 接口方法这一步的postProcessBeforeInitialization中的invokeAwareInterfaces方法进行注入
ApplicationContextAwareProcessor
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
....
invokeAwareInterfaces(bean);
....
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
以上。