若是从单列缓存中没有获取到 Bean 对象,则说明有两种状况:java
针对这两种状况,Spring 是如何处理的呢?统一加载并完成初始化!这部份内容的篇幅较长,拆分为两部分:缓存
代码以下:markdown
//AbstractBeanFactory.java // <3> 由于 Spring 只解决单例模式下得循环依赖,在原型模式下若是存在循环依赖则会抛出异常。 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // <4> 若是当前容器中没有找到,则从父类容器中加载 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); // 若是,父类容器为 AbstractBeanFactory ,直接递归查找 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); // 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象 } else if (args != null) { return (T)parentBeanFactory.getBean(nameToLookup, args); // 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象 } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); // 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象 } else { return (T)parentBeanFactory.getBean(nameToLookup); } } // <5> 若是不是仅仅作类型检查则是建立bean,这里须要记录 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // <6> 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 检查给定的合并的 BeanDefinition checkMergedBeanDefinition(mbd, beanName, args); // <7> 处理所依赖的 bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 若给定的依赖 bean 已经注册为依赖给定的 bean // 即循环依赖的状况,抛出 BeanCreationException 异常 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 缓存依赖调用 TODO 芋艿 registerDependentBean(dep, beanName); try { // 递归处理依赖 Bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // ... 省略不少代码 }复制代码
这段代码主要处理如下几个部分:ide
Spring 只解决单列模式下的循环依赖,对于原型模式的依赖则抛出 BeanCurrentlyInCreationException 异常post
//AbstractBeanFactory.java // 由于 Spring 只解决单例模式下得循环依赖,在原型模式下若是存在循环依赖则会抛出异常。 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } 复制代码
调用 AbstractBeanFactory#isPrototypeCurrentlyInCreation(String beanName) 方法,判断当前 Bean 是否正在建立。代码以下:ui
//AbstractBeanFactory.java //ThreaadLocal 缓存建立的Bean private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal<>("Prototype beans currently in creation"); protected boolean isPrototypeCurrentlyInCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); return (curVal != null && (curVal.equals(beanName)|| (curVal instanceof Set && ((Set<?>)curVal).contains(beanName)))); }复制代码
ThreadLocal 存储的值在单列模式和原型模式是不同的
this
若是当前容器没有找到 Bean ,就从父容器中加载。代码以下:
spa
//AbstractBeanFactory.java // 获取父容器 BeanFactory parentBeanFactory = getParentBeanFactory(); // 检查父容器 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 获取原始 beanName String nameToLookup = originalBeanName(name); // 若是,父类容器为 AbstractBeanFactory ,直接递归查找 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); // 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象 } else if (args != null) { return (T)parentBeanFactory.getBean(nameToLookup, args); // 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象 } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); // 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象 } else { return (T)parentBeanFactory.getBean(nameToLookup); } }复制代码
获取父容器。代码以下:prototype
//AbstractBeanFactory.java private BeanFactory parentBeanFactory; @Override public BeanFactory getParentBeanFactory() { return this.parentBeanFactory; }复制代码
若父容器不为空,而且 beanDefinitionMap 中没有找到对应的 BeanDefinition 对象 。代码以下:code
//DefaultListableBeanFactory.java private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); @Override public boolean containsBeanDefinition(String beanName) { Assert.notNull(beanName, "Bean name must not be null"); return this.beanDefinitionMap.containsKey(beanName); }复制代码
获取原始 beanName。代码以下:
//AbstractBeanFactory.java protected String originalBeanName(String name) { String beanName = transformedBeanName(name); // <x> if (name.startsWith(FACTORY_BEAN_PREFIX)) { // <y> beanName = FACTORY_BEAN_PREFIX + beanName; } return beanName; }复制代码
这里都是委托父容器加载 Bean 的逻辑。代码以下:
// 若是,父类容器为 AbstractBeanFactory ,直接递归查找 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); // 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象 } else if (args != null) { return (T)parentBeanFactory.getBean(nameToLookup, args); // 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象 } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); // 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象 } else { return (T)parentBeanFactory.getBean(nameToLookup); }复制代码
方法参数 typeCheckOnly,表示仅仅进行类型检查获取 Bean 对象。若是不是仅仅作类型检查,而是建立 Bean 对象,则须要调用 AbstractBeanFactory#markBeanAsCreated(String beanName) 方法,进行记录。代码以下:
//AbstractBeanFactory.java // beanName -> RootBeanDefinition private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256); private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); if (!typeCheckOnly) { markBeanAsCreated(beanName); } protected void markBeanAsCreated(String beanName) { // 没有建立 if (!this.alreadyCreated.contains(beanName)) { // 加上全局锁 synchronized (this.mergedBeanDefinitions) { // 再次检查一次:DCL 双检查模式 if (!this.alreadyCreated.contains(beanName)) { // 从 mergedBeanDefinitions 中删除 beanName,并在下次访问时从新建立它。 clearMergedBeanDefinition(beanName); // 添加到已建立 bean 集合中 this.alreadyCreated.add(beanName); } } } } protected void clearMergedBeanDefinition(String beanName) { this.mergedBeanDefinitions.remove(beanName); } 复制代码
//AbstractBeanFactory.java // 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 检查给定的合并的 BeanDefinition checkMergedBeanDefinition(mbd, beanName, args);复制代码
调用 AbstractBeanFactory#getMergedLocalBeanDefinition(String beanName) 获取 RootBeanDefinition 对象。代码以下:
//AbstractBeanFactory.java // beanName -> RootBeanDefinition private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256); protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { // 快速从缓存中获取,若是不为空,则直接返回 RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); if (mbd != null) { return mbd; } // 若是返回的 BeanDefinition 是子类 bean 的话,则合并父类相关属性 return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); } 复制代码
// DefaultListableBeanFactory.java private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); // AbstractBeanFactory.java @Override public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { BeanDefinition bd = this.beanDefinitionMap.get(beanName); if (bd == null) { if (logger.isTraceEnabled()) { logger.trace("No bean named '" + beanName + "' found in " + this); } throw new NoSuchBeanDefinitionException(beanName); } return bd; }复制代码
5.