第一先放我自己画的学习spring的图吧
image.png
一、核心方法refresh()方法走读
- refresh最上层的申明类:是接口:ConfigurableApplicationContext
org.springframework.context.ConfigurableApplicationContext#refresh - refresh的实现类,是抽象类:AbstractApplicationContext。该类实现的refresh方法,其实是通过模板方法实现的。很多调用方法都是其子类实现的。比如:obtainFreshBeanFactory()方法中的refreshBeanFacory()其实现类就是AbstractRefreshableApplicationContext类。其实下面的代码,很多方法都是模板方法,要子类去实现。并且很有可能是好几层后的子类去实现。
org.springframework.context.support.AbstractApplicationContext#refresh代码如下:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
}
-
refresh方法里面,包含了bean解析方法,loadBeanDefinitions方法。由子类实现,比如:AbstractXmlApplicationContext类,该类默认使用XmlBeanDefinitionReader资源解析reader来解析beanDefine。
-
refresh方法里面,解析完了所有的bean之后,就开始初始化了。初始化在finishBeanFactoryInitialization方法中。该方法会遍历beanNames列表,一个一个初始化bean。核心方法就是getBean,该方法的实现在AbstractBeanFactory的doGetBean中。
-
对于doGetBean方法,实现单例,循环依赖功能。当然这里面的细节超级多,这只是一个概要流程。
二、循环依赖源码走读
对于A依赖B,B依赖A的场景。在doGetBean方法中,最开始有行代码,Object sharedInstance = getSingleton(beanName);会判断是否存在过。
解决循环依赖的关键,不在mbd.getDependsOn()方法上。而是在createBean方法里面的populateBean方法。该方法也是AOP实现的核心。最终通过@Resource注解进来的Bean,需要使用
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName)方法来加载依赖的B。但是它不是解决循环依赖的问题关键,它仅仅是完成注解注入的功能。循环依赖的关键,还是在于提前暴露初始化的BeanFactory。
核心:
- 在执行创建BeanA的时候,doCreateBean发现earlySingletonExposure为true,就执行addSingletonFactory()方法,把当前创建的bean加入到singletonFactories对象中。
- 执行A的populateBean方法,发现A依赖了B。转而getBean(B)
- 在执行创建BeanB的时候,同样执行到了doCreateBean发现earlySingletonExposure为true,把当前创建的bean加入到singletonFactories。到此,singletonFactories对象有A和B两个对象了。注意,当前线程还是在执行B的创建,但是已经A和B的最纯对象地址其实已经分配了,放到了singletonFactories对象,提前曝光出来。
- 执行B的populateBean方法,发现了B依赖A。转而getBean(A),执行到getSingleton(beanName)方法时,singletonFactories获取A的对象,不再是空了。进而执行了earlySingletonObjects.put操作。到此,递归创建终于结束了,不在执行createBean操作了。然后B就创建完成了。A终于从populateBean方法返回了。
- 解决了循环依赖,主要是靠如下:earlySingletonExposure为true,向SingletonFactory提早曝光对象。
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
如下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
省略。。。
而getSingleton(beanName)的源码如下:
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
三、singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons的作用,以及加载顺序
定义:
singletonObjects:Bean的单例实例,是初始化之后的
singletonFactories:Bean的原始实例,是调用动态代理生成的原始实例,尚未注册任何依赖,最单纯的实例,没有和任何其他实例Bean建立关系。
earlySingletonObjects:只知道在getSingleton方法的时候,把singletonFactories获取到的对象,put进来。作用还未知???
registeredSingletons:还没了解,好像和singletonObjects同时添加的。
- 首先初次加载一个Bean,会走到doCreateBean方法,然后创建最原始bean的实例,这个时候就调用earlySingletonExposure对象,把原始Bean提前暴露到singletonFactories对象中。
- doCreateBean执行完后,代表这个bean真正的完成了。然后在方法doGetBean的318行执行了getSingleton(beanName, singletonFactory),该方法会把最终的bean添加到singletonObjects对象中,同时会删除singletonFactories和earlySingletonObjects对象中的beanName。
-那么earlySingletonObjects什么是否会添加进去呢?唯一添加的地方如下:
唯一的可能就是只有循环依赖的时候,A创建完成后,创建B,然后B依赖了A。那么在创建B的时候,doGetBean(A)会执行到下面的方法,且这个时候singletonFactories还没来得及remove,这时才有机会把A加入到earlySingletonObjects,然后返回A的singletonFactory,让B顺利完成创建。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
四、自定义bean的初始化方法的实现
有两种实现:
- 继承InitializingBean,重写afterPropertiesSet方法
- spring xml配置,init-method方法
他们两可以同时存在,但是afterPropertiesSet比init-method方法先执行。源码如下:
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 + "'");
}
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();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
//在执行init-method方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
网友评论