🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] <br/> <br/> > ## `BeanFactory` `getBean(name)` ![](https://i.loli.net/2019/03/14/5c89f22fd5838.png) > ### `BeanFactory` ![](https://i.loli.net/2019/03/13/5c888d04acd85.png) * `BeanFactory` ``` public interface BeanFactory { //这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象 String FACTORY_BEAN_PREFIX = "&"; //这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。 Object getBean(String name) throws BeansException; //这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。 <T> T getBean(String name, Class<T> requiredType); <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; //这里提供对bean的检索,看看是否在IOC容器有这个名字的bean boolean containsBean(String name); //这里根据bean名字得到bean实例,并同时判断这个bean是不是单件 boolean isSingleton(String name) throws NoSuchBeanDefinitionException; //这里根据bean名字得到bean实例,并同时判断这个bean是不是原型 boolean isPrototype(String name) throws NoSuchBeanDefinitionException; //这里对得到bean实例的Class类型 Class<?> getType(String name) throws NoSuchBeanDefinitionException; //这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来 String[] getAliases(String name); } ``` * `HierarchicalBeanFactory`,是为了实现bean工厂的层级关系提供支持,其中声明两个方法 ``` //得到父工厂 BeanFactory getParentBeanFactory(); //在本地工厂中有没有给定名称的bean,不包括继承的工厂 boolean containsLocalBean(String name); ``` <br/> > ### `getBean()` ``` public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { // beanName转换 1、移除&开头的字符 2、处理alis别名 final String beanName = transformedBeanName(name); Object bean; //从bean的实例缓存中获取,singletonObjects缓存,map结构 Map<beanName, beanInstance> Object sharedInstance = getSingleton(beanName); // sharedInstance = null,缓存里还没有对应的实例,表明这个实例还没创建。 // BeanFactory 并不会在一开始就将所有的单例 bean 实例化好,而是在调用 getBean 获取时再实例化,懒加载 // ApplicatioContext会在spring启动时先将所有的bean都加载好 // getBean 方法有很多重载,比如 getBean(String name, Object... args) // BeanFactory 会根据这些参数 args 去匹配合适的构造方法构造 bean 实例。 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 + "'"); } } //如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回 //如果sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的bean 实例 //如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回 //FactoryBean 的实现类本身也是一种 bean。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } /* * 如果上面的条件不满足,则表明 sharedInstance 可能为空,此时 beanName 对应的 bean * 实例可能还未创建。这里还存在另一种可能,如果当前容器有父容器,beanName 对应的 bean 实例 * 可能是在父容器中被创建了,所以在创建实例前,需要先去父容器里检查一下。 */ else { //如果上面的条件不满足,则表明 sharedInstance 可能为空,此时 beanName 对应的 bean还未创建 //还存在另一种可能,如果当前容器有父容器,beanName 对应的 bean 实例 可能在父容器中创建了 //所以需要检查一下父容器 // BeanFactory 不缓存 Prototype 类型的 bean,无法处理该类型 bean 的循环依赖问题 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 如果 sharedInstance = null,则到父容器中查找 bean 实例 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 获取 name 对应的 beanName,如果 name 是以 & 字符开头,则返回 & + beanName String nameToLookup = originalBeanName(name); // 根据 args 是否为空,以决定调用父容器哪个方法获取 bean if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 合并父 BeanDefinition 与子 BeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 检查是否有 dependsOn 依赖,如果有则先初始化所依赖的 bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { //检测是否存在 depends-on 循环依赖 //depends-on 循环,Spring 会直接 抛出异常 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 注册依赖记录 registerDependentBean(dep, beanName); try { // 加载 depends-on 依赖 getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 创建 bean 实例 if (mbd.isSingleton()) { /* * 这里并没有直接调用 createBean 方法创建 bean 实例,而是通过 * getSingleton(String, ObjectFactory) 方法获取 bean 实例。 * getSingleton(String, ObjectFactory) 方法会在内部调用 * ObjectFactory 的 getObject() 方法创建 bean,并会在创建完成后, * 将 bean 放入缓存中。关于 getSingleton 方法的分析,本文先不展开,我会在 * 后面的文章中进行分析 */ 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 实例。否则直接返回 bean 实例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 创建 prototype 类型的 bean 实例 else if (mbd.isPrototype()) { Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // 创建其他类型的 bean 实例 else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); 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.isInstance(bean)) { 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()); } } // 返回 bean return (T) bean; } ``` > ### `beanName`转换 * 处理以字符 `&` 开头的 `name`,处理别名。 ``` protected String transformedBeanName(String name) { // 这里调用了两个方法: // BeanFactoryUtils.transformedBeanName(name) 处理&字符 //canonicalName 转换别名 return canonicalName(BeanFactoryUtils.transformedBeanName(name)); } ``` <br/> > ### 从缓存中获取`bean`实例。 * 对于单例`bean`,`Spring`容器只会实例化一次。后续再次获取时,只需直接从缓存里获取即可,无需且不能再次实例化。 * 从缓存中取`bean`实例的方法是`getSingleton(String)`。 ``` public Object getSingleton(String beanName) { return getSingleton(beanName, true); } // allowEarlyReference表示是否允许其他 bean 引用正在创建中的 bean,用于处理循环引用的问题。 protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 从 singletonObjects 获取实例,singletonObjects 中缓存的实例都是完全实例化好的 bean,可以直接使用 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 从 earlySingletonObjects 中获取提前曝光的 bean,用于处理循环引用 singletonObject = this.earlySingletonObjects.get(beanName); // 如果如果 singletonObject = null,且允许提前曝光 bean 实例,则从相应的 ObjectFactory 获取一个原始的(raw)bean(尚未填充属性) if (singletonObject == null && allowEarlyReference) { // 获取相应的工厂类,获取对应beanName的工厂类 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 提前曝光 bean 实例,用于解决循环依赖 //此处为实际创建bean实例 singletonObject = singletonFactory.getObject(); // 放入上级缓存,如果还有其他 bean 依赖当前 bean,其他 bean 可以直接从 earlySingletonObjects 取结果 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } ``` * 其中涉及了三个缓存 ![](https://i.loli.net/2019/03/12/5c87952a56166.png) <br/> > ### 合并父 BeanDefinition 与 子 BeanDefinition * `Spring` 支持配置继承,在标签中可以使用`parent`属性配置父类 `bean`。这样子类 `bean` 可以继承父类 `bean` 的配置信息,同时也可覆盖父类中的配置。比如下面的配置: ``` <bean id="hello" class="xyz.coolblog.innerbean.Hello"> <property name="content" value="hello"/> </bean> <bean id="hello-child" parent="hello"> <property name="content" value="I`m hello-child"/> </bean> ``` <br/> > ### 从 `FactoryBean` 中获取 `bean` 实例 * 单例类型,将`FactoryBean`生成的`bean`放入缓存 * 非单例,每次创建新的`bean` *** > ### 参考 #### [Spring IOC 容器源码分析 - 循环依赖的解决办法](https://segmentfault.com/a/1190000015221968) #### [Spring IOC 容器源码分析 - 获取单例 bean](http://www.tianxiaobo.com/2018/06/01/Spring-IOC-%E5%AE%B9%E5%99%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E8%8E%B7%E5%8F%96%E5%8D%95%E4%BE%8B-bean/) #### [Spring IOC 容器源码分析系列文章](http://www.tianxiaobo.com/2018/05/30/Spring-IOC-%E5%AE%B9%E5%99%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0%E5%AF%BC%E8%AF%BB/)