之前的文章:
2、深入理解Spring IOC(二) 、从xml到BeanDefinition
3、深入理解Spring IOC(三) 、refresh方法中实例化前的准备工作
接下来我们进入AbstractApplicationContext中的finishBeanFactoryInitialization这个方法,我们先一起看看它的代码:
代码块1
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 先实例化ConversionService(如果有)
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 实例化LoadTimeWeaverAware的实现类
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// 在这里要将beanDefiniton冻结住,因为要进行实例化了,不希望beanDefiniton有任何的变化
beanFactory.freezeConfiguration();
// 要实例化几乎除过实现了BeanFactoryPostProcessor、BeanPostProcessor的类之外的所有类
// 因为这两个的实现类之前已经实例化过了
beanFactory.preInstantiateSingletons();
}
前面的代码不属于重要的部分,我们直接看最后一处的方法preInstantiateSingletons,该方法的实现位于DefaultListableBeanFactory中:
代码块2
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
List<String> beanNames;
synchronized (this.beanDefinitionMap) {
// this.beanDefinitionNames,创建beanDefinitionNames的副本beanNames
// 用于后续的遍历,以允许init等方法注册新的bean定义
// this.beanDefinitionNames 中存储的是在注册BeanDefinition的时候存进来的bean名称
beanNames = new ArrayList<String>(this.beanDefinitionNames);
}
// 遍历,用bean名称初始化
for (String beanName : beanNames) {
// 获取beanName对应的RootBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 如果不是抽象并且是单例,并且不是懒加载,才会去进行初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 1. 如果不是FactoryBean就直接初始化,是的话先拿到FactoryBean本身,再根据isEagerInit决定
// 是否调用getObject进行初始化
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
// 2.这个if else主要是用于判断是否需要先加载(饥饿加载)
// isEagerInit这个变量值其实就是SmartFactoryBean中isEagerInit()方法,只不过一个是直接获取,
// 另外一个是通过“特权”去执行
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
// 如果isEagerInit则实例化bean
if (isEagerInit) {
getBean(beanName);
}
} else {
getBean(beanName);
}
}
}
}
我们来看代码块2的1处调用的isFactoryBean方法
代码块2.1
代码块3
@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
// 1. 处理名称
String beanName = transformedBeanName(name);
// 2. 从缓存中拿实例并判断
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {
return (beanInstance instanceof FactoryBean);
// 如果this.singletonObjects包含这个beanName的key,则直接返回false
}else if (containsSingleton(beanName)) {
return false;
}
// 从beanDefinition中做检查
// 本BeanFactory对象中没有这个beanName的BeanDefinition && 父BeanFactory是个ConfigurableBeanFactory
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
// 根据class判断是不是个FactoryBean
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
首先看看代码块3中1处处理名称的逻辑:
代码块3.1
代码块4
protected String transformedBeanName(String name) {
// 调用canonicalName方法去处理BeanFactoryUtils.transformedBeanName的结果
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
上面代码块调用的方法参数是BeanFactoryUtils中的transformedBeanName返回的,我们先来看这个方法:
代码块5
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
String beanName = name;
// beanName 是否以 “&” 开头,如果以它开头,将这个用String中的substring方法截掉
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
return beanName;
}
很多人会疑惑,为什么以“&”开头,就截取掉呢?我们来看看BeanFactory中定义的“&”的地方:
代码块6
public interface BeanFactory {
/**
* Used to dereference a {@link FactoryBean} instance and distinguish it from
* beans <i>created</i> by the FactoryBean. For example, if the bean named
* {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
* will return the factory, not the instance returned by the factory.
*/
String FACTORY_BEAN_PREFIX = "&";
.....
我们可以清楚的从这个变量的注释上面看到:如果某个bean是个FactoryBean类型的东西,但是它注册进IOC容器的名称是用“&”开头,那么代表它想获取的是FactoryBean本身,而不是它的getObject所返回的对象。因此,去拿真正的bean的名称的时候是需要去掉这个前缀的。然后我们继续看代码块4调用的这个canonicalName方法
代码块4.1
代码块7
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// 去根据别名拿真正的名称
// aliasMap的key是别名,value是名称
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
我们再回到代码块3,来看里面2处的方法,注意此时第二个参数是false:
代码块3.2
代码块8
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);
// ***** 如果半成品也是null并且允许创建早期的单例引用,
if (singletonObject == null && allowEarlyReference) {
// 去拿对象的ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 通过ObjectFactory创建半成品,然后放到半成品对象的缓存中
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
注意注释中*开头的,因为此时传过来的参数是false,所以在这之后的代码此时都是没有被执行的。这段代码涉及到三层缓存的概念,所谓的三层缓存,其实就是singletonObjects,earlySingletonObjects,singletonFactories这三个Map,这三层缓存对解决循环依赖有着重要的意义,如果你现在不明白,就当混个脸熟,完了回过头来看,相信会容易理解很多,现在可以理解为这个方法就是从缓存里取已经创建的bean实例的。
代码块2.2
我们继续看代码块2的第2处isEagerInit属性的获取这里,因为对于spring来说,它去拿这个isEagerInit属性,很可能是去调用第三方jar包的东西,而这个第三方jar包却需要操作一些需要权限才可以操作的东西,因此这里如果检测到SecurityManager,说明程序是有权限校验的,这时候就需要通过AccessController.doPrivileged来执行。我们接下来看这里调用的getBean方法:
代码块9
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
可以看到这个方法是直接调用的doGetBean,我们来看看这个方法:
代码块10
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 1. 解析bean的名称
final String beanName = transformedBeanName(name);
Object bean;
// 2.先尝试从缓存中取一波
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 3. 这块这个主要是针对FactoryBean的处理,如果只是个普通bean,则直接返回其本身
// 如果是个FactoryBean,则要根据name判断
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 4. 这个主要针对的是prototype(多例)的bean的循环依赖的检查(spring解决不了多例的循环依赖)
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果父BeanFactory存在,并且本BeanFactory中不存在这个beanName的BeanDefinition
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 5. 将别名解析成真正的bean的名字
String nameToLookup = originalBeanName(name);
// 使用父BeanFactory创建实例
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// 6. 如果不是仅仅检查类型,则把beanName放到alreadyCreated缓存中
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
// 注意哈:其实到这里,真正创建bean的流程才开始
try {
// 7. 拿到这个beanName对应的BeanDefinition对应的RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 将mbd打印成json (这是作者自己增加的代码)
System.out.println(JSON.toJSON(mbd).toString());
// 8. 检查这个mbd是否合法
checkMergedBeanDefinition(mbd, beanName, args);
// 先实例化这个bean所依赖的bean,mbd.getDependsOn()是获取mbd所
// 依赖的bean实例的名称(xml中对应bean标签depend-on属性)
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
// 这块这个是检查循环依赖的
// 例:如果有这么两个类A和B,A中有个成员属性B,B中有个成员属性A,当先实例化A的时候,发现B还没有实例化
// 然后去调用上面的getBean方法(相当于递归),然后走到这里发现B又依赖A,然后就报异常了
// 这个会在两个bean标签的depend-on属性相互指向对方时发生
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
// 9. 将依赖关系注册
registerDependentBean(dependsOnBean, beanName);
// 然后实例化依赖的那个bean
getBean(dependsOnBean);
}
}
// 这里开始创建mbd对应的bean
// 创建单例
if (mbd.isSingleton()) {
// 10. 获取bean实例
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 调用创建bean的方法
return createBean(beanName, mbd, args);
}catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
// 返回bean本身,(这个方法我们之前讲过,是针对FactoryBean处理的那个方法)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
// 创建prototype的bean
}else if (mbd.isPrototype()) {
// 如果是个prototype的实例,那就创建个新的
Object prototypeInstance = null;
try {
// 11. 创建prototype前的检查
beforePrototypeCreation(beanName);
// 调用创建bean的方法
prototypeInstance = createBean(beanName, mbd, args);
}finally {
// 12.创建prototype后的检查
afterPrototypeCreation(beanName);
}
// 返回bean本身,(和上面if一个方法)
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
// 创建其他scope的bean
}else {
String scopeName = mbd.getScope();
// 拿到对应scope的缓存
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
// 创建bean实例,注意这里重写了ObjectFactory的getObject方法
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
// 创建prototype前的检查
beforePrototypeCreation(beanName);
try {
// 调用创建bean的方法
return createBean(beanName, mbd, args);
}finally {
// 创建prototype后的检查
afterPrototypeCreation(beanName);
}
}
});
// 返回bean本身,(和上面if一个方法)
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 检查类型,如果不是结果所需要的类型,则尝试类型转换
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
这个方法代码比较长,我们对着我的注释,一个一个来看,1处在上面已经讲过,这里和上面的逻辑是完全一样的,我们来看代码块10中2处的代码所调用的方法:
代码块10.2
代码块11
@Override
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
这里调用的方法还是代码块8的那个方法,只不过注意此时参数为true了,true和上面的false有什么区别呢?我们可以翻到代码块8看看,当这个参数为true的时候,是允许使用ObjectFactory来创建早期的引用的,不过你可能还不明白什么是早期引用,没关系,先记住这个问题,继续往下看,自然会明白。
我们继续回到代码块10中,去看第3处代码,你应该注意到,能走到这处,说明上面从缓存中取出来的sharedInstance应该不是null,并且本方法参数中args要为null,我们在代码块9中可以看到args确实是null,所以可以肯定,如果sharedInstance不是null,那的确是可以进到3这里来的:我们来看看3处调用的方法。
代码块10.3
代码块12
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 1.如果名称是个factorybean前缀(&)开头的但是却不是FactoryBean,则抛出异常
// (当bean名称前缀是“&”的时候,代表这玩意是个FactoryBean的实例)
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 2.if的前半个条件意思是如果不是FactoryBean,则直接返回beanInstance
// 后半个条件是当是个FactoryBean的时候,并且用&开头,则返回beanInstance
// (以“&”为前缀代表想获取的是FactoryBean本身,而不是它getObject返回的)
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 3.当代码走到这里的时候,beanInstance一定是一个FactoryBean
// 并且想要返回的是FactoryBean中getObject所返回的,object即为返回的结果
Object object = null;
if (mbd == null) {
//4. 尝试从factoryBeanObjectCache(factoryBean创建的对象的缓存)里拿
object = getCachedObjectForFactoryBean(beanName);
}
// 如果从factoryBean创建的对象的缓存没拿到,就走这个if
if (object == null) {
//5. 因为一定是FactoryBean,所以可以直接强转
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
//6. 如果mbd为空,并且beanDefinitionMap中包含着这个bean,则去根据这个获取RootBeanDefinition
if (mbd == null && containsBeanDefinition(beanName)) {
// 7. 获取beanName对应的RootBeanDefinition
mbd = getMergedLocalBeanDefinition(beanName);
}
//8. 判断Beaneifinition是不是合成的(多次debug这里都是false)
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
第1处的注释写的很清楚,我们来看看它调用的方法:
代码块13
public static boolean isFactoryDereference(String name) {
// BeanFactory.FACTORY_BEAN_PREFIX 值是“&”
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
是不是很简单?其实源码中很多地方也没那么难的,第2处也很简单了,我们来看看第4处调用的方法的代码:
代码块14
// 下面方法调用的cache
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<String, Object>(16);
protected Object getCachedObjectForFactoryBean(String beanName) {
// factoryBeanObjectCache就是factoryBean创建的对象的缓存
Object object = this.factoryBeanObjectCache.get(beanName);
return (object != NULL_OBJECT ? object : null);
}
这个也是个很简单的方法,我们继续看代码块12中的第6处的这个if条件里调用的方法:
代码块15
@Override
public boolean containsBeanDefinition(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return this.beanDefinitionMap.containsKey(beanName);
}
这个beanDefinitionMap就是我们之前讲注册beanDefinition时候的那个map,我们再继续看代码块12中的第8处代码,注意我把第7处的跳过了哈,因为现在不是讲这个第7处方法调用的代码的最好时候,你现在先去根据注释理解,等该讲的时候,我会让你一下子明白的。
代码块16
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// FactoryBean实例是单例 && FactoryBean实例已经存在单例缓存this.singletonObjects中
if (factory.isSingleton() && containsSingleton(beanName)) {
// getSingletonMutex()返回的是单例缓存this.singletonObjects
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 1. 使用factoryBean创建bean
object = doGetObjectFromFactoryBean(factory, beanName);
// 如果缓存中已经存在,则用缓存中的替换上面生成的
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}else {
// 2. 既然object已经生成了,则执行所有BeanPostProcessor的
// postProcessAfterInitialization方法
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
// 放入factoryBeanObjectCache缓存
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
return (object != NULL_OBJECT ? object : null);
}
}else {
// 使用factoryBean创建bean,然后再执行所有的BeanPostProcessor(和上面一样)
// 不同点是prototype这种情况的话,不会放到缓存中
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
直接来看代码块16里第1处调用的方法:
代码块17
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
// 就是简单调用了FactoryBean的getObject而已,只不过if
// 代码块的是特权调用,else里是直接调用
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
}catch (PrivilegedActionException pae) {
throw pae.getException();
}
}else {
object = factory.getObject();
}
}catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// 如果结果object此时还是null,并且这个FactoryBean还是在创建的这个过程中,则
// 抛出异常,此时说明初始化流程是存在问题的
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
return object;
}
这段代码是也是段纸老虎代码,看着很长,其实很简单,就是调用了FactoryBean的getObject方法而已,我们再来看代码块16的if中调用的代码,注意真正被调用的方法在AbstractAutowireCapableBeanFactory中:
代码块18
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
// 执行所有BeanPostProcessor的postProcessAfterInitialization方法
Object result = existingBean;
// 遍历执行
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
至此,代码块10中的3处就完了,是不是感觉费了很久功夫呢?其实阅读源码就是这样,方法中套方法,经常都是你看完了一个很长的方法,再回到原来的方法,发现其实只是这个方法中的一行代码,我早些时候经常都是边看边吐血,因为真的太难了,不过好在一遍又一遍的坚持了下来,完了还是很开心的。
代码块10.4
小小的吐槽完了,继续看代码块10中的第4处,这里主要是针对prototype的循环依赖检查,这个是当A中有B,B中有A并且A和B的scope都是prototype的时候会在这里抛异常,spring解决不了prototype的循环依赖,原因也简单,你想嘛,你想要一个新的A,创建A的时候发现A需要一个新的B,所以要去创建B,但是创建B的时候,又要一个新的A,然后就陷入无限循环,最后要么StackOverFlowException,要么OutOfMemoryError,所以spring就在这里直接抛异常了。
代码块10.5
接下来是代码块10的第5处调用的方法,这个方法是用来获取bean的原始名称的:
代码块19
protected String originalBeanName(String name) {
String beanName = transformedBeanName(name);
// 如果name中有"&",那就给beanName也加上“&”
// 因为transformedBeanName中去掉了“&”
if (name.startsWith(FACTORY_BEAN_PREFIX)) {
beanName = FACTORY_BEAN_PREFIX + beanName;
}
return beanName;
}
第一行的代码解释见代码块5,剩下的很简单了,我们继续代码块10中的第6处调用的方法:
代码块10.6
代码块20
protected void markBeanAsCreated(String beanName) {
// alreadyCreated 是已经创建的和正准备去创建的集合
if (!this.alreadyCreated.contains(beanName)) {
this.alreadyCreated.add(beanName);
}
}
依然是个很简单的方法,代码块10中第6处调用这个方法,是因为准备去创建这个bean了。我们继续代码块10中第7处,这下要讲这个之前代码块12和代码块2中跳过的getMergedLocalBeanDefinition(String name)方法了,我们先贴出来这个方法的代码哈:
代码块10.7
代码块21
// 首先调用的方法
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// 看看缓存中有没有,如果有的话直接返回
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
// 调用下面的方法
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
// 继续调用下面的方法
return getMergedBeanDefinition(beanName, bd, null);
}
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, BeanDefinition containingBd) throws BeanDefinitionStoreException {
// 加锁防止并发
synchronized (this.mergedBeanDefinitions) {
// 这个是返回结果
RootBeanDefinition mbd = null;
// Check with full lock now in order to enforce the same merged instance.
// 之所以还在这里get一下,是因为防止从上面的方法到这里的时候已经有别的线程把这个RootBeanDefinition创建好了
// 现在在这个串行的操作中,如果没有get到,说明就是确实还没有
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
// 若不存在于缓存中,则进行下一步操作
if (mbd == null) {
if (bd.getParentName() == null) {
// 如果没有父定义的BeanDefinition,则不需要合并,直接通过深克隆的方式
// 创建RootBeanDefinition
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
} else {
mbd = new RootBeanDefinition(bd);
}
} else {
// 存在父定义BeanDefinition,递归着去和父定义的合并
BeanDefinition pbd;
try {
// 获取父BeanDefinition真正的名称
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
// 递归调用
pbd = getMergedBeanDefinition(parentBeanName);
} else {
if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// 强转再递归调用
pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
} else {
throw new NoSuchBeanDefinitionException(bd.getParentName(),
"Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// 根据父定义深度拷贝一个新的
mbd = new RootBeanDefinition(pbd);
// 用子覆盖父
mbd.overrideFrom(bd);
}
// 默认单例
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// 设置scope,此时containingBd还是null
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// containingBd是null && this.cacheBeanMetadata && 该bean是否可以被缓存
// 这里这三个条件走到这块一般都成立了
if (containingBd == null && isCacheBeanMetadata() && isBeanEligibleForMetadataCaching(beanName)) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
return mbd;
}
}
这个方法的代码不算难,但是为什么要把其他类型的BeanDefinition都转成RootBeanDefinition呢?因为RootBeanDefinition是被spring作为在运行时候的统一使用的BeanDefnition(即在创建bean实例时候使用的统一的BeanDefnition),里面还包含了解析过的构造方法缓存,方法参数缓存其他缓存信息,如果说其他类型的BeanDefnition都是用于把元数据(就是如xml或者注解)表达为spring可以认识的信息的话,那么RootBeanDefinition就是把spring已经认识出来的信息表达为了可以实际去使用的信息。
我们继续看代码块10中第8处方法调用的方法:
代码块10.8
代码块22
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args)
throws BeanDefinitionStoreException {
// 如果是抽象则抛出异常
if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
// 如果args不是null但是beanDefinition对应的类型却不是prototype,则抛出异常
// 这个是因为当args不是null的时候,代表需要动态参数实例化bean,而此时该bean的作用域只能是prototype
if (args != null && !mbd.isPrototype()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"Can only specify arguments for the getBean method when referring to a prototype bean definition");
}
}
代码块22我没有标数字,我稍微解释一下这里面的第二处注释,方法参数args不为null的情况是当你调用了applicationContext中带参数的getbean方法或者是beanFactory中带参数的getbean方法时候,这里才不是null,但是高版本的spring已经把这个对参数检查去掉了。
代码块10.9
继续看代码块10中第9处,此时已经找到我们这个beanName对应的bean需要依赖的bean是哪些bean了,因此将依赖关系注册进去:
代码块23
public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取真正的bean名称
String canonicalName = canonicalName(beanName);
// 这段代码是将beanName和dependentBeanName的依赖关系注册到dependentBeanMap中
// 注意这个是beanName依赖dependentBeanName
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
dependentBeans = new LinkedHashSet<String>(8);
this.dependentBeanMap.put(canonicalName, dependentBeans);
}
dependentBeans.add(dependentBeanName);
}
// 这段代码是将beanName和dependentBeanName的依赖关系注册到dependentBeanMap中
// 注意这个是dependentBeanName依赖beanName,关系是反着的
// 就是说当A中有B,B中有A和C的时候,C中又有A,spring通过这两个map就能知道
// A依赖了B,而依赖A的有A和C
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
if (dependenciesForBean == null) {
dependenciesForBean = new LinkedHashSet<String>(8);
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
}
dependenciesForBean.add(canonicalName);
}
}
里面第一行注释调用的方法在本篇的代码块7已经讲过,其他的都很容易理解了,我们继续回过头来看代码块10中的第10处,在看这里调用的getSingleton方法之前,你需要注意到这个getSingleton方法和之前的不一样,此外,这个方法调用的时候所传的第二参数是个实现了ObjectFactory的匿名内部类,并且在它的实现里面调用了createBean方法,限于篇幅,createBean方法会在下一篇讲,不然估计你可能会晕的更厉害。我们来看这里的getSingleton方法,注意这个getSingleton和上面代码块8的不是一个方法:
代码块10.10
代码块24
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 如果当前beanFactory处在destruction状态中,则不允许创建bean
// 这个状态指的是beanFactory执行了destroySingletons方法,即applicationContext执行close方法会调用到这个方法
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while the 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 + "'");
}
// 1. 创建单例前的检查
beforeSingletonCreation(beanName);
// suppressedExceptions用户记录在创建期间出现的异常
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
// 调用ObjectFactory来创建bean
singletonObject = singletonFactory.getObject();
}catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 2. 创建单例后的检查
afterSingletonCreation(beanName);
}
// 将创建出来的bean放到缓存中
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
我们来看上面的代码块中1,创建单例前的检查:
代码块25
protected void beforeSingletonCreation(String beanName) {
// 检查bean是否要包含在检查已经创建的集合中,如果不是,则看bean是否在创建中
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
然后是代码块24中的2,创建单例后的检查:
代码块26
protected void afterSingletonCreation(String beanName) {
// 检查bean是否要包含在检查已经创建的集合中,如果不是,则从正在创建的集合中移除,
// 移除失败则抛异常
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
getSingleton方法完了,我们继续回到代码块10看11处的创建prototype前的检查:
代码块10.11
代码块27
@SuppressWarnings("unchecked")
protected void beforePrototypeCreation(String beanName) {
// 从当前线程正在创建的prototype中拿所有的正在创建的集合
Object curVal = this.prototypesCurrentlyInCreation.get();
// 如果curlVal是空,则设置当前bean为正在创建的bean
if (curVal == null) {
this.prototypesCurrentlyInCreation.set(beanName);
// 如果不是空并且是个String(代表有一个在创建中),则创建集合,并且把curVal
// 和当前beanName都加进去
} else if (curVal instanceof String) {
Set<String> beanNameSet = new HashSet<String>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
// 这种的说明是有两个以上的在创建,直接加入正在创建的集合中去
} else {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
接下来是代码块10看12处:
代码块10.12
代码块29
@SuppressWarnings("unchecked")
protected void afterPrototypeCreation(String beanName) {
// 获取正在创建的prototype的集合
Object curVal = this.prototypesCurrentlyInCreation.get();
// 如果是String则直接remove掉
if (curVal instanceof String) {
this.prototypesCurrentlyInCreation.remove();
}
// 如果是set则从set中删除
else if (curVal instanceof Set) {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.remove(beanName);
if (beanNameSet.isEmpty()) {
this.prototypesCurrentlyInCreation.remove();
}
}
}
至此doGetBean方法已经讲完,下一篇,我们开始createBean方法