目录
- 添加到一级缓存的时机
- doGetBean方法中创建单例Bean的代码
- getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法源码
- addSingleton方法源码
- 添加到二级缓存的时机
- doGetBean中首次调用getSingleton
- 添加到三级缓存的时机
- doGetBean方法调用addSingletonFactory方法的源码
- addSingletonFactory方法源码
- 总结
三个缓存都存在于DefaultSingletonBeanRegistry中。以AbstractBeanFactory中的getBean作为入口。
添加到一级缓存的时机
一级缓存主要用于存储单例模式下创建完毕的Bean实例,包括该Bean的实例化,依赖注入,初始化等都完成的一个完整的Bean。
所以添加到一级缓存中的时机:自然是完成Bean的实例化,依赖注入,初始化等操作,生成完整的单例Bean后进行添加的。
源码位置:getBean方法——doGetBean方法——getSingleton创建单例Bean——addSingleton方法
doGetBean方法中创建单例Bean的代码
可以看到,getSingleton方法的入参传入是ObjectFactory类型,使用匿名内部类的方式,传入一个实现了ObjectFactory类的getObject方法的对象,getObject方法通过调用createBean方法完成对象的创建。
if (mbd.isSingleton()) {sharedInstance = this.getSingleton(beanName, () -> {try {return this.createBean(beanName, mbd, args);} catch (BeansException var5) {this.destroySingleton(beanName);throw var5;}});beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}
getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法源码
1、该方法使用synchronized对一级缓存进行加锁。
2、获取到锁后从一级缓存中取Bean对象,取到则直接返回
3、缓存中取不到,则调用ObjectFactory的getObject方法创建对象
4、最后调用addSingleton方法,把单例Bean添加到缓存中
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 (this.logger.isDebugEnabled()) {this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");}this.beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = this.suppressedExceptions == null;if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet();}try {singletonObject = singletonFactory.getObject();newSingleton = true;} catch (IllegalStateException var16) {singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {throw var16;}} catch (BeanCreationException var17) {BeanCreationException ex = var17;if (recordSuppressedExceptions) {Iterator var8 = this.suppressedExceptions.iterator();while(var8.hasNext()) {Exception suppressedException = (Exception)var8.next();ex.addRelatedCause(suppressedException);}}throw ex;} finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}this.afterSingletonCreation(beanName);}if (newSingleton) {this.addSingleton(beanName, singletonObject);}}return singletonObject;}}
addSingleton方法源码
1、该方法使用synchronized对一级缓存进行加锁。获取singletonObjects锁
2、调用put方法添加到一级缓存
3、清理三级缓存singletonFactories中的该Bean
4、清理二级缓存earlySingletonObjects中的该Bean
5、把该Bean添加到成功列表中,registeredSingletons记录已经创建成功的单例名称。
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);}}
添加到二级缓存的时机
源码位置:getBean方法——doGetBean方法——getSingleton方法
doGetBean中首次调用getSingleton
getSingleton(beanName)此方法先从一级和二级缓存中取,如果都取不到,允许从三级缓存中取,如果从三级缓存中取到Bean。
如果从三级缓存中取到对应的Bean,则把Bean添加到二级缓存,并在三级缓存中清除
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {String beanName = this.transformedBeanName(name);Object sharedInstance = this.getSingleton(beanName);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {synchronized(this.singletonObjects) {singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();// 添加到二级缓存this.earlySingletonObjects.put(beanName, singletonObject);// 在三级缓存中清除this.singletonFactories.remove(beanName);}}}}}}return singletonObject;}
添加到三级缓存的时机
调用createBeanInstance进行Bean实例化之后,调用populateBean进行依赖注入之前
源码位置:getBean方法——doGetBean方法——addSingletonFactory方法
doGetBean方法调用addSingletonFactory方法的源码
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);if (earlySingletonExposure) {if (this.logger.isTraceEnabled()) {this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");}this.addSingletonFactory(beanName, () -> {return this.getEarlyBeanReference(beanName, mbd, bean);});}
addSingletonFactory方法源码
1、获取锁
2、添加到三级缓存
3、从二级缓存中进行清理
4、把该Bean添加到成功列表中,registeredSingletons记录已经创建成功的单例名称。
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(singletonFactory, "Singleton factory must not be null");synchronized(this.singletonObjects) {if (!this.singletonObjects.containsKey(beanName)) {this.singletonFactories.put(beanName, singletonFactory);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}}
总结
添加到一级缓存:完成Bean的实例化,依赖注入,初始化等操作,生成完整的单例Bean后进行添加。
添加到二级缓存:通过getBean获取实例,在三级缓存中获取到时,添加到二级缓存,并清理三级缓存。
添加到三级缓存:通过createBeanInstance实例化Bean之后,调用populateBean进行依赖注入之前。