文章目录
IOC容器的对象存储
1、单例Bean对象
spring主要通过BeanFactory接口的getBean方法来从IOC容器,即BeanFactory的实现类中获取某个bean对象实例,但是BeanFactory并不直接操作bean对象的存取,而是通过BeanRegistry的接口来处理,类似读写分离的概念。其中,单例bean的注册和获取通过实现SingletonBeanRegistry接口,分别对应registerSingleton和getSingleton方法,其实现类为DefaultSingletonBeanRegistry,已注册的单例bean就保存在该实现类的singletonObjects缓存map中,此外还包括用于处理循环依赖的三级缓存等。单例bean对象的存取实际就是在这些map中进行
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** 单例bean缓存: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 三级缓存:单例对象工厂: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 二级缓存:早期单例bean对象缓存: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
/** 已注册的单例bean名称 */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** 当前正在创建的bean名称,防止重复创建,比如处理循环依赖时使用. */
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//注册单例bean对象
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
addSingleton(beanName, singletonObject);
}
}
//添加单例bean对象到ioc容器
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
//获取单例bean
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
2、工厂Bean(FactoryBean)对象
FactoryBean创建的bean对象容器FactoryBeanRegistrySupport:继承于DefaultSingletonBeanRegistry,factoryBeanObjectCache 中的bean对象实例是通过调用FactoryBean的getObject方法获取的bean对象。
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
}
3、完整的IOC容器
BeanFactory的基础抽象实现类AbstractBeanFactory继承了BeanFactory接口和SingletonBeanRegistry接口,具备完整的IOC功能入口
Bean对象的完整加载流程
spring主要通过ApplicationContext来对外提供IOC服务,即与应用代码集成,而不是在应用代码中直接使用BeanFactory。通过ApplicationContext来初始化BeanFactory和从BeanFactory获取应用所需的bean对象。其中applicationContext的完整生命周期主要定义在AbstractApplicationContext的refresh方法中
applicationContext生命周期
-
prepareRefresh
主要做一些准备工作,比如initPropertySources 初始化上下文环境中的占位符属性源 -
obtainFreshBeanFactory
获取一个全新的BeanFacory, 如果context是AbstractRefreshableApplicationContext的子类,比如XmlApplicationContext,则创建完beanFacory后直接调用loadBeanDefinitions来从配置文件中加载所有bean -
prepareBeanFactory(beanFactory);
为beanFactory添加基础配置,比如设置BeanClassLoader、添加BeanPostProcessor(ApplicationContextAwareProcessor、ApplicationListenerDetector)、添加自动装配忽略的接口依赖(EnvironmentAware、ApplicationContextAware等)、注册可解析的依赖(BeanFactory、ApplicationContext等)、注册默认的环境相关bean(environment、systemProperties、systemEnvironment) -
postProcessBeanFactory(beanFactory);
在加载完bean但还没有实例化之前操作,比如增加beanPostProcessor等。
在web相关的子类实现中处理:如注册ServletContextAwareProcessor;注册scope(request、session、globalSession、application);
注册环境bean实例(servletContext、servletConfig、contextParameters、contextAttributes -
invokeBeanFactoryPostProcessors(beanFactory);
调用PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法,实例化并调用所有已注册的BeanFactoryPostProcessor,主要是对ConfigurationClassPostProcessor的调用处理
注册BeanDefinitionRegistryPostProcessor实例并调用:注册ConfigurationClassPostProcessor遍历所有BeanDefinition,使用ConfigurationClassParser处理所有candidates:
处理@PropertySources、@ComponentScan,使用ComponentScanAnnotationParser处理;处理@ImportResource;处理@Bean methods,之后使用ConfigurationClassBeanDefinitionReader.loadBeanDefinitions注册bean和类中的@Bean 及autowire、initMethod、destroyMethod
registerBeanDefinitionForImportedConfigurationClass
loadBeanDefinitionsForBeanMethod
loadBeanDefinitionsFromImportedResources
loadBeanDefinitionsFromRegistrars
- registerBeanPostProcessors(beanFactory);
调用PostProcessorRegistrationDelegate.registerBeanPostProcessors方法,实例化并注册所有BeanPostProcessor,在bean实例化之前调用
添加BeanPostProcessorChecker;获取所有BPP, 将实现 PriorityOrdered、Ordered 和其余的BPP分开注册所有PriorityOrdered BPP:比如:CommonAnnotationBeanPostProcessors,AutowireAnnotaionBeanPostProcessors,RequirdAnnotaionBeanPostProcessors;
注册册所有Ordered BeanPostProcessors:比如:AnnotationAwareAspectJAutoProxyCreator
注册所有普通BeanPostProcessors:注册ApplicationListenerDetector
-
initMessageSource();
用于国际化i18n -
initApplicationEventMulticaster();
注册事件多播器 -
onRefresh();
模板方法供子类实现,用于在bean实例化之前进行特殊处理,如注册themeSource -
registerListeners();
注册所有实现了ApplicationListener的监听器,注册到applicationEventMulticaster -
finishBeanFactoryInitialization(beanFactory);
bean实例化,完成bean从beanDefinition到bean实例的整个过程,也就是我们关心的bean对象的完整加载过程就在这里进行,主要入口在DefaultListableBeanFactory的preInstantiateSingletons方法中 -
finishRefresh();
完成此上下文的刷新,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent
以上是ApplicationContext的整个初始化过程,而我们关心的bean对象由BeanDefinition转化为Bean实例对象的完整流程入口主要在finishBeanFactoryInitialization方法中,即DefaultListableBeanFactory的preInstantiateSingletons方法。
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//返回一个合并的 RootBeanDefinition,合并父Bean特性
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//如果非抽象类且单例且非懒加载则执行Bean实例化
if (isFactoryBean(beanName)) { //判断是是否是工厂Bean
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else { //如果不是工厂bean则直接调用getBean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
下面详细分析下整个过程
单例bean加载流程
1、依次进入AbstractBeanFactory的getBean、doGetBean方法。先调用getSingleton检查三级缓存,如果存在bean实例则返回,否则的话校验prototypesCurrentlyInCreation中是否存在该beanName,prototypesCurrentlyInCreation是定义的一个本地线程变量,用来保存当前正在创建的bean名称,如果该本地线程变量中存在该beanName,则抛出一个疑似循环依赖的异常;
2、获取parentBeanFactory并检查当前beanFactory是否存在该beanDefinition,如果不存在并且parentBeanFactory不为空的话则调用parentBeanFactory的getBean方法,交给parentBeanFactory来创建bean对象;
3、遍历依赖bean(通过@DependsOn注解或depends-on配置的依赖组件),并对每个依赖bean调用getBean方法,确保每个依赖的bean先被实例化;
4、如果是单例bean则调用getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法获取单例bean对象,其中singletonFactory的getObject方法主要是调用createBean方法,进入真正的创建bean实例的过程;
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//先从一级单例缓存中获取bean实例对象
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//校验是否在销毁状态中
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//校验inCreationCheckExclusions中如果不存在并且singletonsCurrentlyInCreation已经存在的话则抛出循环依赖异常
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//调用createbean方法创建bean实例对象
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//从singletonsCurrentlyInCreation中移除,校验inCreationCheckExclusions和singletonsCurrentlyInCreation 中如果都不存在则抛异常
afterSingletonCreation(beanName);
}
if (newSingleton) {
//添加到一级缓存中,同时从二三级缓存中移除
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
5、进入creatBean方法,该方法定义在AbstractAutowireCapableBeanFactory抽象类中。首先调用resolveBeanClass,确保bean对应的class类已经被解析,之后调用resolveBeforeInstantiation方法,使用InstantiationAwareBeanPostProcessor的实现类AbstractAutoProxyCreator的applyBeanPostProcessorsBeforeInstantiation来处理bean的代理类,用于返回一个代理对象,实现AOP。如果applyBeanPostProcessorsBeforeInstantiation返回的bean不为空,则调用applyBeanPostProcessorsAfterInitialization方法,即遍历所有BeanPostProcessors并调用postProcessAfterInitialization方法,最后直接返回该代理对象。
6、如果上述代理类为空则进入doCreateBean方法,进入创建bean实例对象的核心流程。
-
6.1 调用createBeanInstance方法,使用构造函数创建bean实例
在determineConstructorsFromBeanPostProcessors方法中调用AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors方法,基于贪婪原则选择能注入最多bean对象的构造函数,如果只存在一个显式定义的构造函数,则使用这个构造函数;否则先基于构造函数的参数个数对所有构造函数进行降序排序,然后遍历检查这些构造函数。选中最合适的构造函数后,则进行构造函数的属性对象的注入。
主要是在createArgumentArray方法处理构造函数的属性注入问题,最终会调用到BeanFactory的getBean方法从BeanFactory获取所依赖的其他对象。如果BeanFactory当前还不存在该依赖的bean对象,则会在getBean方法中创建该bean对象并返回。所以如果该被依赖的bean对象如果也在构造函数中依赖了当前正在创建的bean对象,则该依赖的bean对象就无法创建了,故出现了循环依赖问题,导致程序异常退出。 -
6.2 调用applyMergedBeanDefinitionPostProcessors
调用MergedBeanDefinitionPostProcessor实现类的postProcessMergedBeanDefinition方法,主要处理有以下两种:
1、AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition处理注入的字段、方法(@Autowired、@Value等)
2、CommonAnnotationBeanPostProcessor 处理@PostConstruct、@PreDestroy等 -
6.3 添加到三级缓存用于解决循环依赖问题
如果是单例并且allowCircularReferences为ture即允许循环依赖并且singletonsCurrentlyInCreation中存在该beanName的话则添加到三级缓存singletonFactories中,用于处理循环依赖问题。其中singletonFactory主要是通过SmartInstantiationAwareBeanPostProcessor的实现类AbstractAutoProxyCreator的getEarlyBeanReference方法
-
6.4 调用populateBean方法填充Bean属性
1、先调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation,在设置属性之前修改 bean。例如,这可以用于支持字段注入的样式。
2、autowireByName或者autowireByType,通过名称或者类型进行依赖注入,如果是这种方式出现的循环依赖则spring能完美解决
3、调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法进行属性值注入和setter方法注入
4、applyPropertyValues -
6.5 调用initializeBean方法初始化bean,应用接口回调方法和init方法
1、调用invokeAwareMethods,如果类实现了BeanNameAware、BeanClassLoaderAware和BeanFactoryAware则调用对应的set方法进行属性注入
2、调用applyBeanPostProcessorsBeforeInitialization方法,即调用所有BeanPostProcessor的postProcessBeforeInitialization方法
3、调用invokeInitMethods方法,如果实现了InitializingBean则调用afterPropertiesSet方法,然后调用自定义init方法(在bean标签的init-method中指定的处理方法或者使用@Bean注解的initMethod的指定方法)
4、调用applyBeanPostProcessorsAfterInitialization方法,即调用所有BeanPostProcessor的postProcessAfterInitialization方法 -
6.6 调用registerDisposableBeanIfNecessary,将beanName添加到disposableBeans缓存中
disposableBeans的key为beanName,value为new一个DisposableBean的实现类DisposableBeanAdapter的对象。在spring容器关闭时,从AbstractApplicationContext的doClose开始,调用BeanFactory的destroySingletons,最终销毁每个singleton的时候,从以上disposableBeans获取该bean对应的DisposableBeanAdapter,然后调用DisposableBeanAdapter的destroy。
DisposableBeanAdapter的destroy方法实现如下:先调用DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法,再调用DisposableBean,最后调用destroy-method。
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
以上,即spring bean的完整加载流程。