各scope的Bean创建
在 Spring 中存在着不同的 scope,默认是 singleton ,还有 prototype、request 等其他的 scope 。
singleton
Spring 的 scope 默认为 singleton :
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
|
如果缓存中不存在bean呢?则需要从头开始加载 Bean ,这个过程由 getSingleton(String beanName, ObjectFactory singletonFactory)
方法来实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| 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 + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { 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; } }
protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
|
这个过程并没有真正创建 Bean 对象,仅仅只是做了一部分准备和预处理步骤。真正获取单例 bean 的方法,其实是由 <3>
处的 singletonFactory.getObject()
这部分代码块来实现,而 singletonFactory
由回调方法产生。
该方法做的准备:
<1>
处,再次检查缓存是否已经加载过,如果已经加载了则直接返回,否则开始加载过程。
<2>
处,调用 beforeSingletonCreation(String beanName)
方法,记录加载单例 bean 之前的加载状态,即前置处理,标记为正在创建中。在从缓存中获取单例Bean已经介绍。
<3>
处,调用参数传递的 ObjectFactory 的 getObject()
方法,实例化 bean 。
<4>
处,调用 afterSingletonCreation(String beanName)
方法,进行加载单例后的后置处理,删除标记为正在创建中。
<5>
处,调用 addSingleton(String beanName, Object singletonObject)
方法,将结果记录并加入值���存中,同时删除加载 bean 过程中所记录的一些辅助状态。
加载完单例Bean后,调用 getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd)
方法,从 bean 实例中获取对象。在从缓存中获取单例Bean已经介绍。
prototype
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
else if (mbd.isPrototype()) { Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
|
原型模式的初始化过程很简单:直接创建一个新的 Bean 的实例就可以了。
- 在
<1>
处,调用 beforePrototypeCreation(String beanName)
方法,记录加载原型模式 bean 之前的加载状态,即前置处理。
- 在
<2>
处,调用 createBean(String beanName)
方法,创建一个 bean 实例对象。
- 在
<3>
处,调用 afterSingletonCreation(String beanName)
方法,进行加载原型模式 bean 后的后置处理。
- 在
<4>
处,加载了单例 bean 后,调用 getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd)
方法,从 bean 实例中获取对象。在从缓存中获取单例Bean已经介绍。
beforePrototypeCreation()
方法
注册为当前正在创建。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
protected void beforePrototypeCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); if (curVal == null) { this.prototypesCurrentlyInCreation.set(beanName); } else if (curVal instanceof String) { Set<String> beanNameSet = new HashSet<>(2); beanNameSet.add((String) curVal); beanNameSet.add(beanName); this.prototypesCurrentlyInCreation.set(beanNameSet); } else { Set<String> beanNameSet = (Set<String>) curVal; beanNameSet.add(beanName); } }
|
afterPrototypeCreation()
方法
标记为不在创建中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
protected void afterPrototypeCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); if (curVal instanceof String) { this.prototypesCurrentlyInCreation.remove(); } else if (curVal instanceof Set) { Set<String> beanNameSet = (Set<String>) curVal; beanNameSet.remove(beanName); if (beanNameSet.isEmpty()) { this.prototypesCurrentlyInCreation.remove(); } } }
|
其他scope
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| else { String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'"); } 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, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new ScopeNotActiveException(beanName, scopeName, ex); } }
|
核心流程和原型模式一样,只不过获取 bean 实例是由 Scope.get(String name, ObjectFactory objectFactory)
方法来实现,处理方式和单例模式一样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
private final ThreadLocal<Map<String, Object>> threadScope = new NamedThreadLocal<Map<String, Object>>("SimpleThreadScope") { @Override protected Map<String, Object> initialValue() { return new HashMap<>(); } };
@Override public Object get(String name, ObjectFactory<?> objectFactory) { Map<String, Object> scope = this.threadScope.get(); Object scopedObject = scope.get(name); if (scopedObject == null) { scopedObject = objectFactory.getObject(); scope.put(name, scopedObject); } return scopedObject; }
|
总结
比较重要的两个:
createBean(String beanName, RootBeanDefinition mbd, Object[] args)
方法。
getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd)
方法。在从缓存中获取单例Bean已经介绍。
以上两个方法在单例、原型、其他模式中都有调用。不过在单例和其他模式中,createBean()
是以回调方式出现的。
getObjectForBeanInstance()
这个方法主要是验证以下我们得到的 bean 的正确性,其实就是检测当前 bean 是否是 FactoryBean 类型的 bean 。
如果是,那么需要调用该 bean 对应的 FactoryBean 实例的 getObject()
方法,作为返回值。
无论是从缓存中获得到的 bean 还是通过不同的 scope 策略加载的 bean 都只是最原始的 bean 状态,并不一定就是我们最终想要的 bean。
举个例子,加入我们需要对工厂 bean 进行处理,那么这里得到的其实是工厂 bean 的初始状态,但是我们真正需要的是工厂 bean 中定义 factory-method
方法中返回的 bean,而 getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd)
方法,就是完成这个工作的。