AbstractBeanFactory#getBean(beanName)
由于 getBean 内容比较多, 所以单独出来, 接着上一篇的顺序来看.
//org.springframework.beans.factory.support.AbstractBeanFactory#getBean @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }
doGetBean里面, 有一堆乱七八糟的判断,
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { /** * 通过 name 获取 beanName。这里不使用 name 直接作为 beanName 有两个原因 * 1、name 可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean * 实现类所创建的 bean。在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储 * 方式是一致的,即 <beanName, bean>,beanName 中是没有 & 这个字符的。所以我们需要 * 将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。 * 2、还是别名的问题,转换需要 * &beanName */ final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. /** * 这个方法在初始化的时候会调用,在getBean的时候也会调用 * 为什么需要这么做呢? * 也就是说spring在初始化的时候先获取这个对象 * 判断这个对象是否被实例化好了(普通情况下绝对为空====初始化完之后, 此处返回就不是空了) * 从spring的bean容器中获取一个bean,由于spring中bean容器是一个map(singletonObjects) * 所以你可以理解getSingleton(beanName)等于beanMap.get(beanName) * 由于方法会在spring环境初始化的时候(就是对象被创建的时候调用一次)调用一次 * 还会在getBean的时候调用一次 * * 需要说明的是在初始化时候调用一般都是返回null */ 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 + "'"); } } /** * 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。 * 但如果 sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的 bean 实例。 * 如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回即可。 * 毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。 */ bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. /** * 原型模式 * 如果是原型不应该在初始化的时候创建 */ if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { ...... } if (!typeCheckOnly) { //添加到 alreadyCreated set集合当中,表示他已经创建过一场 markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); //bd检测, 如果是 abstract, 则抛异常 checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. // 单例创建 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { ...... } else { ...... } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isInstance(bean)) { ...... } return (T) bean; }
方法比较长, 我删掉一部分. 不影响观看.
主要看两个方法 :
1.getSingleton(String beanName, ObjectFactory<?> singetonFactory)
2.createBean
getSingleton
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { 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 + "'"); } /** * 将beanName添加到singletonsCurrentlyInCreation这样一个set集合中 * 表示beanName对应的bean正在创建中 */ beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { //这里会调用传入的 lambda 表达式创建的匿名 singletonFactory 对象, 调用他的 getObject() 方法 //其方法内部, 也就是调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean 方法 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; } //把标识为正在创建的标识去掉 afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
这里的getSingleton , 明显是一个创建 bean 的地方.
1. 在创建之前, 通过 beforeSingletonCreation() 方法, 执行了 this.singletonsCurrentlyInCreation.add(beanName) 这句代码,
这里其实是在做一个标志, 表示 这个 beanName 对应的 bean 正在创建当中. 将 singletonsCurrentlyInCreation 翻译过来, 就能看懂.
这里做到了变量名的命名就是最好的注释.
2. 调用 factory.getObject 方法, 进行 bean 的创建, 调用的其实就是 createBean() 方法.
3. 创建完成之后, 通过 afterSingletonCreation() 方法, 将标志位改回去, 其内部执行了 this.singletonsCurrentlyInCreation.remove(beanName) 这句代码.
4. 在最后, 通过 addSingleton() 方法, 将创建的 bean 放到 spring 容器中 : this.singletonObjects.put(beanName, singletonObject)
这里的这个顺序很重要, 尤其是那个 正在创建的标志, 很重要的 : singletonsCurrentlyInCreation
这个正在创建的标志, 在解决 循环依赖的时候, 起了很重要的作用
createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } //Prepare method overrides. //处理xml中的 lookup-method 和 replace-method 配置,Spring将这两个配置统称为override method try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 在 bean实例化之前 应用后置处理,如果后置处理返回的bean不为空,则直接返回 // 返回的是一个寡妇对象, 属性什么的, spring不会去维护 // spring不推荐开发人员使用这个接口 InstantiationAwareBeanPostProcessor Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { // 创建bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
在 spring 里面, 有一个习惯, 喜欢把 真正干活的那个方法, 以 do 开头.
所以, 这个 doCreateBean() 方法, 应该就是干活方法.
不过在此之前, 要看一个重要扩展方法: resolveBeforeInstantiation