接上回, AbstractApplicationContext#refresh
调用 AbstractApplicationContext#finishBeanFactoryInitialization
来初始化所有的非懒加载单例Bean。在该 AbstractApplicationContext#finishBeanFactoryInitialization
方法内部通过调用 AbstractBeanFactory#doGetBean
来获取Spring容器所管理的Bean。
AbstractBeanFactory#doGetBean
源码如下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 如果这个 name 是 FactoryBean 的beanName (&+beanName),就删除& , 返回beanName ,传入的name也可以是别名,也需要做转换 // 注意 beanName 和 name 变量的区别,beanName是经过处理的,经过处理的beanName就直接对应singletonObjects中的key final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. // 根据beanName尝试从singletonObjects获取Bean // 获取不到则再尝试从earlySingletonObjects,singletonFactories 从获取Bean // 这段代码和解决循环依赖有关 Object sharedInstance = getSingleton(beanName); // 第一次进入sharedInstance肯定为null 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 + "'"); } } // 如果sharedInstance不为null,也就是非第一次进入 // 为什么要调用 getObjectForBeanInstance 方法,判断当前Bean是不是FactoryBean,如果是,那么要不要调用getObject方法 // 因为传入的name变量如果是(&+beanName),那么beanName变量就是(beanName),也就是说,程序在这里要返回FactoryBean // 如果传入的name变量(beanName),那么beanName变量也是(beanName),但是,之前获取的sharedInstance可能是FactoryBean,需要通过sharedInstance来获取对应的Bean // 如果传入的name变量(beanName),那么beanName变量也是(beanName),获取的sharedInstance就是对应的Bean的话,就直接返回Bean 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为null,如果存在父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); } } // 创建的Bean是否需要进行类型验证,一般情况下都不需要 if (!typeCheckOnly) { // 标记 bean 已经被创建 markBeanAsCreated(beanName); } try { // 获取其父类Bean定义,子类合并父类公共属性 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. // 获取当前Bean依赖的Bean的名称 ,@DependsOn String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 如果当前Bean依赖其他Bean,把被依赖Bean注册给当前Bean registerDependentBean(dep, beanName); try { // 先去创建所依赖的Bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. if (mbd.isSingleton()) { // 创建单例Bean 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. // 创建prototype Bean,每次都会创建一个新的对象 Object prototypeInstance = null; try { // 回调beforePrototypeCreation方法,注册当前创建的原型对象 beforePrototypeCreation(beanName); // 创建对象 prototypeInstance = createBean(beanName, mbd, args); } finally { // 回调 afterPrototypeCreation 方法,告诉容器该Bean的原型对象不再创建 afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { // 如果既不是单例Bean,也不是prototype,则获取其Scope 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, () -> { 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. // 对创建的Bean进行类型检查 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; } 复制代码
主要流程都已经在上述的源码中增加了注释,读者可以自己查阅。其中,我觉得最主要是要明白以下几点:
Object sharedInstance = getSingleton(beanName);
这段代码是解决循环依赖的关键,先大概看一下,留个印象,具体的等后面后空讲一下循环依赖吧。
public Object getSingleton(String beanName) { return getSingleton(beanName, true); } //getSingleton(beanName, true);源码 @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { //singletonObjects 就是Spring内部用来存放单例Bean的对象池,key为beanName,value为Bean Object singletonObject = this.singletonObjects.get(beanName); // singletonsCurrentlyInCreation 存放了当前正在创建的bean的BeanName if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // earlySingletonObjects 是早期单例Bean的缓存池,此时Bean已经被创建(newInstance),但是还没有完成初始化 // key为beanName,value为Bean singletonObject = this.earlySingletonObjects.get(beanName); //是否允许早期依赖 if (singletonObject == null && allowEarlyReference) { //singletonFactories 单例工厂的缓存,key为beanName,value 为ObjectFactory ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { //获取早期Bean singletonObject = singletonFactory.getObject(); //将早期Bean放到earlySingletonObjects中 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } 复制代码
调用 doGetBean
方法时会传入 name
变量,表明需要从容器中获取那个Bean。 transformedBeanName
除了在处理别名之后,这里会有以下几种情况:
@Bean public UserBean userBean() { return new UserBean("shen", 111); } 复制代码
在这种情况下, name
变量如果为 userBean
,那么就是要从容器中获取 UserBean
对象。
调用 transformedBeanName
方法返回 beanName
对象的取值 userBean
。
然后根据 beanName
去容器中获取相应的 Bean
,而获取到的就是 UserBean
对象。
最后调用 getObjectForBeanInstance
方法,返回的还是 UserBean
对象。
第二种情况,通过 FactoryBean
往容器中注册Bean
@Bean public FactoryBean userBean() { return new FactoryBean<UserBean>() { @Override public UserBean getObject() throws Exception { return new UserBean("shen", 111); } @Override public Class<?> getObjectType() { return UserBean.class; } }; } 复制代码
这里又可以分为两种情况:
如果 name
变量如果为 userBean
,那么也要从容器中获取 UserBean
对象。
调用 transformedBeanName
方法返回 beanName
对象的取值为 userBean
。
然后根据 beanName
去容器中获取相应的 Bean
,而获取到的是 FactoryBean
对象。
最后调用 getObjectForBeanInstance
方法,发现是从容器中获取 UserBean
对象,于是调用 FactoryBean#getObject
返回 UserBean
对象。
name
变量如果为 &userBean
,那么就是要从容器中获取 FactoryBean
对象本身。
调用 transformedBeanName
方法返回 beanName
对象的取值为 userBean
。
然后根据 beanName
去容器中获取相应的 Bean
,而获取到的是 FactoryBean
对象,
最后调用 getObjectForBeanInstance
方法,就是要获取 FactoryBean
对象,于是方法返回 FactoryBean
对象。
通过源码可以知道,Spring在创建Bean之前,首先会创建当前Bean所有依赖的Bean。
String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 如果当前Bean依赖其他Bean,把被依赖Bean注册给当前Bean registerDependentBean(dep, beanName); try { // 先去创建所依赖的Bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } 复制代码
那什么是当前Bean所有依赖的Bean呢?也就是说, String[] dependsOn = mbd.getDependsOn();
什么情况下这个数组中会有值呢?
在Spring中有这个一个注解: @DependsOn
。这个注解一般用的很少(碰巧最近项目中用到了这个注解,哈哈哈)。来看一下Spring文档中是怎么描述的:
Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialization. A depends-on declaration can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency. Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, a depends-on declaration can also control shutdown order.
机器翻译:当前bean所依赖的bean。任何指定的bean都保证在此bean之前由容器创建。当一个bean不是通过属性或构造函数参数显式依赖于另一个bean,而是依赖于另一个bean初始化的副作用时,很少使用。依赖项声明既可以指定初始化时间依赖项,也可以指定(在只有单例bean的情况下)对应的销毁时间依赖项。在销毁给定bean之前,首先销毁定义与给定bean的依赖关系的依赖bean。因此,依赖声明也可以控制关机顺序。
@Service public class OrderService { public OrderService() { System.out.println("OrderService create"); } @PreDestroy public void destroy() { System.out.println("OrderService destroy"); } } 复制代码
@DependsOn("orderService") @Service public class UserService { public UserService() { System.out.println("UserService create"); } @PreDestroy public void destroy() { System.out.println("UserService destroy"); } } 复制代码
@Configuration @ComponentScan public class DependsOnMain { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DependsOnMain.class); context.close(); } } 复制代码
//允许结果 OrderService create UserService create UserService destroy OrderService destroy 复制代码
在Spring中存在者多种scope,Spring会根据不用的scope选用不同的初始化方式。但是,不管怎么样,Spring在底层创建Bean的时候都是通过调用 AbstractAutowireCapableBeanFactory#createBean
方法来创建对象的。
那Spring究竟是怎么创建Bean的呢? AbstractAutowireCapableBeanFactory#createBean
方法内部到底做了什么事情呢?循环依赖该怎么解决呢?
未完待续...
源码注释GITHUB地址: github.com/shenjianeng…
欢迎关注微信公众号: