整体流程
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.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 + "'");}}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所以该分支目前也不会走BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}// typeCheckOnly falseif (!typeCheckOnly) {// 标记为已创建,并放入alreadyCreated缓冲中markBeanAsCreated(beanName);}try {// 获取bean定义RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 如果是抽象类会抛出异常 BeanIsAbstractExceptioncheckMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.// 保证bean配置的依赖都已经实例化了。<bean class="xxx" depends-on="xxxx">String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// 遍历实例化依赖的beanfor (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()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}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);}});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;}}// Check if required type matches the type of the actual bean instance.if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;}
transformedBeanName
然后进入 doGetBean 方法,这里面代码很多,分成小段来看。
第一个小段:transformedBeanName 转换 bean 的名称,都给了 beanName 为啥还要转换?因为 bean 是有别名的,需要把这个别名转换成最终指向的 bean 的 beanName.
spring-beans | org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
@SuppressWarnings("unchecked")protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {String beanName = transformedBeanName(name);Object bean;.....}
protected String transformedBeanName(String name) {return canonicalName(BeanFactoryUtils.transformedBeanName(name));}
调用静态方法,这个方法还是比较容易理解的,如下所示:
spring-beans | org.springframework.beans.factory.BeanFactoryUtils#transformedBeanName
public static String transformedBeanName(String name) {Assert.notNull(name, "'name' must not be null");// 如果不是FactoryBean就直接返回。(FactoryBean的开头是&)if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {return name;}// 如果是FactoryBean的话,返回去掉&的名称,同时加入缓存,例如:{&hello=hello}return transformedBeanNameCache.computeIfAbsent(name, beanName -> {do {beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());}while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));return beanName;});}
然后是 canonicalName 方法,规范化名字,利用别名缓存把别名转换成真正的名字
spring-core | org.springframework.core.SimpleAliasRegistry#canonicalName
public String canonicalName(String name) {String canonicalName = name;// Handle aliasing...String resolvedName;do {resolvedName = this.aliasMap.get(canonicalName);if (resolvedName != null) {canonicalName = resolvedName;}}while (resolvedName != null);return canonicalName;}
getSingleton
得到 bean 的名称后,从缓存中尝试获取这个bean的实例。
spring-beans | org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
@Override@Nullablepublic Object getSingleton(String beanName) {// 参数true表示允许早期依赖return getSingleton(beanName, true);}
进入方法,从三个缓存中进行判断
spring-beans | org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton
@Nullableprotected Object getSingleton(String beanName, boolean allowEarlyReference) {// Quick check for existing instance without full singleton lock// 从单例bean缓存中查找。称为:第一级缓存,用于存放完全初始化好的beanObject singletonObject = this.singletonObjects.get(beanName);// 从"bean状态:创建中"的缓存中查找。if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {// 从早期单例bean缓存中查找。// 称为:第二级缓存,提前曝光的单例对象的cache,存放原始的bean对象(尚未填充属性),用于解决循环依赖singletonObject = this.earlySingletonObjects.get(beanName);// 如果允许引用的话if (singletonObject == null && allowEarlyReference) {// 同步操作synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton locksingletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {// 从singletonFactories缓存中判断。称为:第三级缓存ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {// 得到对象singletonObject = singletonFactory.getObject();// 加入二级缓存this.earlySingletonObjects.put(beanName, singletonObject);// 去掉三级缓存this.singletonFactories.remove(beanName);}}}}}}return singletonObject;}
首先从 singletonObjects 里面获取实例,如果获取不到再从 earlySingleObjects 里面获取,如果还获取不到再从 singleFactories 里面获取对应的 ObjectFactory,然后利用其 getObject 方法来获取 bean 并放到 earlySingleObjects 里面,再从 singleFactories 中移除该 ObjectFactory .
代码执行流程图:
这里也是三级缓存解决循环依赖的处理办法,详情见:Spring 利用三级缓存解决循环依赖的方式!
getObjectForBeanInstance
接下来就会有两个大分支,一是从缓存中没有拿到对象,另一个是拿到了。
无论走哪个分支,最后都会调用 getObjectForBeanInstance 这个方法。因为我们得到 bean 的实例后要做的第一件事就是验证一下正确性✅ ,其实就是检测一下这个实例是不是 FactoryBean 类型的 bean,如果是就调用 getObject() 方法得到的返回值作为最终的 bean.
org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.// 表明用户想要获取 factoryBean 实例if (BeanFactoryUtils.isFactoryDereference(name)) {if (beanInstance instanceof NullBean) {return beanInstance;}// 如果bean是工厂相关(名称特点:&beanName),但是 beanInstance 又不是 FactoryBean实例,异常if (!(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());}if (mbd != null) {mbd.isFactoryBean = true;}return beanInstance;}// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.if (!(beanInstance instanceof FactoryBean)) {return beanInstance;}Object object = null;if (mbd != null) {mbd.isFactoryBean = true;} else {// 尝试从缓存中获取beanobject = getCachedObjectForFactoryBean(beanName);}if (object == null) {// Return bean instance from factory.FactoryBean<?> factory = (FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.if (mbd == null && containsBeanDefinition(beanName)) {// 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition// 如果指定BeanName是子Bean的话同时会合并父类的相关属性mbd = getMergedLocalBeanDefinition(beanName);}// 是否用户自定义的配置,而不是程序本身定义的boolean synthetic = (mbd != null && mbd.isSynthetic());object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;}
流程:
- 该方法首先判断用户想要的是不是 FactoryBean ,因为 FactoryBean 的名称开头是 & 符号,并且做了些校验;
- 如果不是 FactoryBean 直接返回;
- 如果 FactoryBean 想要得到具体 bean 的话,首先尝试从缓存获取 bean;
- 如果缓存中没有的话,利用 FactoryBean 来创建 bean,创建就交给了 getObjectFromFactoryBean 方法。
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {// 单例已注册的beanif (factory.isSingleton() && containsSingleton(beanName)) {synchronized (getSingletonMutex()) {Object object = this.factoryBeanObjectCache.get(beanName);if (object == null) {object = doGetObjectFromFactoryBean(factory, beanName);// Only post-process and store if not put there already during getObject() call above// (e.g. because of circular reference processing triggered by custom getBean calls)// 从缓存中判断是否已经存在了Object alreadyThere = this.factoryBeanObjectCache.get(beanName);if (alreadyThere != null) {object = alreadyThere;}else {if (shouldPostProcess) {// 可能在循环原理中,直接返回if (isSingletonCurrentlyInCreation(beanName)) {// Temporarily return non-post-processed object, not storing it yet..return object;}// bean状态设置为创建中,加入 singletonsCurrentlyInCreation 缓存beforeSingletonCreation(beanName);try {// 执行处理器.object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName,"Post-processing of FactoryBean's singleton object failed", ex);}finally {// bean 从 singletonsCurrentlyInCreation 缓存中移除afterSingletonCreation(beanName);}}if (containsSingleton(beanName)) {this.factoryBeanObjectCache.put(beanName, object);}}}return object;}}else {// 非单例的beanObject object = doGetObjectFromFactoryBean(factory, beanName);if (shouldPostProcess) {try {object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);}}return object;}}
过程:
- 单例的从缓存中先判断,然后再调用方法 doGetObjectFromFactoryBean 创建,再执行各种处理器;
- 多例的直接调用方法 doGetObjectFromFactoryBean 创建,然后执行各种处理器;(以为多例的不缓存);
所以最终创建的方法是 doGetObjectFromFactoryBean
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName)throws BeanCreationException {Object object;try {// 权限验证if (System.getSecurityManager() != null) {AccessControlContext acc = getAccessControlContext();try {object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>)factory::getObject, acc);}catch (PrivilegedActionException pae) {throw pae.getException();}}else {// 获取 beanobject = factory.getObject();}}catch (FactoryBeanNotInitializedException ex) {throw new BeanCurrentlyInCreationException(beanName, ex.toString());}catch (Throwable ex) {throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);}// Do not accept a null value for a FactoryBean that's not fully// initialized yet: Many FactoryBeans just return null then.// 不接受null,为空返回 NullBeanif (object == null) {if (isSingletonCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");}object = new NullBean();}return object;}
过程:
- 首先做权限验证;
- 然后调用方法 getObject 创建 bean;
对于返回 null 是不允许的,包装成 NullBean。否则正常返回就行了。
缓存有对象
// 如果从缓存中拿到了实例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 + "'");}}// 注册并得到创建好的对象bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}
从缓存中获取到了对象后,就调用 getObjectForBeanInstance 方法获取即可。
缓存无对象
缓存中没有的话,就需要进行创建对象了。
// 从缓存中没有拿到实例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所以该分支目前也不会走BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}// typeCheckOnly falseif (!typeCheckOnly) {// 标记为已创建,并放入alreadyCreated缓冲中markBeanAsCreated(beanName);}try {// 获取bean定义RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 如果是抽象类会抛出异常 BeanIsAbstractExceptioncheckMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.// 保证bean配置的依赖都已经实例化了。<bean class="xxx" depends-on="xxxx">String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// 遍历实例化依赖的beanfor (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()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}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);}});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;}}
缓存中没有对象,这个情况很好模拟。加载一个普通的 bean 即可,比如
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN""https://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans><bean id="user" class="cn.lichenghao.entity.User"><property name="name"><value>Rod</value></property><property name="age"><value>31</value></property></bean></beans>
public class App2 {public static void main(String[] args) {// 根据配置文件加载beanClassPathXmlApplicationContext classPathXmlApplicationContext= new ClassPathXmlApplicationContext("bean.xml");User bean = classPathXmlApplicationContext.getBean(User.class);bean.sayHello();}}
默认情况下是单例,并且也没有设置过父 BeanFactory 所以前两个小分支也不会走,直接到了下面。
if (!typeCheckOnly) {// 标记为已创建markBeanAsCreated(beanName);}
来到方法。
spring-beans | org.springframework.beans.factory.support.AbstractBeanFactory#markBeanAsCreated
protected void markBeanAsCreated(String beanName) {if (!this.alreadyCreated.contains(beanName)) {synchronized (this.mergedBeanDefinitions) {if (!this.alreadyCreated.contains(beanName)) {// Let the bean definition get re-merged now that we're actually creating// the bean... just in case some of its metadata changed in the meantime.clearMergedBeanDefinition(beanName);this.alreadyCreated.add(beanName);}}}}
这块代码就是利用了两了缓存,alreadyCreated,mergedBeanDefinitions 。标记📌 就进入了 alreadyCreated 缓存。
这块的代码全都是为了后面的创建bean在做准备。那么也到了处理bean的最重要的环节:createBean 。
