接下来我们进入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处调用的方法。