[Sping] Spring 源码分析之 Bean 的加载

Bean的加载过程分析

参考死磕系列

ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
Students s = (Students) ctx.getBean("stu2");

追踪源码到 AbstractBeanFactorydoGetBean 方法:
(把源码贴出来,在源码中加上了注释)

内部调用 doGetBean() 方法,其接受四个参数:

  • name:要获取 bean 的名字
  • requiredType:要获取 bean 的类型
  • args:创建 bean 时传递的参数。这个参数仅限于创建 bean 时使用
  • typeCheckOnly:是否为类型检查
	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
        // 转换BeanName,根据 name 获取真正的 beanName 或 FactroyBean 的 name
		final String beanName = transformedBeanName(name);
		Object bean;
        // 从缓存中或者实例工厂中获取 bean
        // 这里会涉及到解决循环依赖 bean 的问题
		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			// 从缓存中取到了Bean,再进一步做实例化处理
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
             // 只解决单例模式下循环依赖的问题,
             // 判断是不是原型模式下的bean,如果是的话,则抛出异常 
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
            // 从父类容器中加载bean
			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

            // // 如果不是仅仅做类型检查则是创建bean,这里需要记录
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
			     // 从容器中获取 beanName 相应的 GenericBeanDefinition,并将其转换为 RootBeanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 检查给定的合并的 BeanDefinition
				checkMergedBeanDefinition(mbd, beanName, args);

                // 处理所依赖的 bean
				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
					// 如果dependsOnBean已经注册为了beanName的依赖bean,则抛出异常
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException("Circular depends-on relationship between '" +
									beanName + "' and '" + dependsOnBean + "'");
						}
					    // 注册依赖的bean
						registerDependentBean(dependsOnBean, beanName);
						// 递归getBean方法获取bean
						getBean(dependsOnBean);
					}
				}

                // 单例模式,bean的实例化
				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							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);
				}
                // 原型模式,bean的实例化
				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);
				}
                // 从指定的 scope 下创建 bean
				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								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 的实际类型
		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type [" +
							ClassUtils.getQualifiedName(requiredType) + "]", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

梳理为以下步骤:

  1. 获取beanName ,代码如下:
final String beanName = transformedBeanName(name);
	protected String transformedBeanName(String name) {
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}

	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		String beanName = name;
		// 去除beanFactory的修饰符,如果 beanName 是以 & 开头的,则截取掉 &  
		while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
		}
		return beanName;
	}
     
    // 转换别名
	public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do { 
		    // 根据别名取到真正的beanName
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}
  1. 从单例 bean 缓存中获取 bean 对应代码段如下:
Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

单例模式的 Bean 在 Bean 的整个生命周期当中只创建一次,第一次创建后将将Bean 加载到缓存当中,以后加载 Bean 时就都从单例缓存里取。 如果从缓存中得到了 Bean ,就调用 getObjectForBeanInstance() 方法,对Bean 进行实例化处理,因为缓存中记录的是最原始的 bean 状态,我们得到的不一定是我们最终想要的 bean。

如果没有从缓存中获取到Bean,则到了下边的逻辑:
3. 原型模式依赖检查与 parentBeanFactory 对应代码段

            // spring 只解决单例模式下的循环依赖问题,对于原型模式的话直接抛出异常
            // Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

            // 获取 parentBeanFactory来加载Bean
			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			// 如果parentBeanFactory  不为空,且 该Bean没有注册 BeanDefinition缓存中,则使用 parentBeanFactory 加载 Bean
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				// 获取原始的 BeanName
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

如果容器缓存中没有相对应的 BeanDefinition 则会尝试从父类工厂(parentBeanFactory)中加载,然后再去递归调用 getBean()。

  1. 类型检查
            // 如果不是类型检查,则要记录bean的创建
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}
  1. RootBeanDefinition 处理:
try {
                // 将存储在 XML配置文件中的GemericBeanDefinition 转换为 RootBeanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

  1. 依赖处理:
// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				// 存在依赖
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException("Circular depends-on relationship between '" +
									beanName + "' and '" + dependsOnBean + "'");
						}
						//注册依赖关系
						registerDependentBean(dependsOnBean, beanName);
						getBean(dependsOnBean);
					}
				}

因为 bean 的初始化过程中很坑用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他bean,那么这个时候就有必要先加载依赖的bean 。所以, 在Spring的加载过程中,在初始化某一个bean的时候首先会初始化这个bean 所对应的依赖。

  1. 根据bean的作用域对bean实例化
// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							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();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								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;
			}

registerDependentBean(dependsOnBean, beanName) 注册依赖关系
比如,加载 A 的时候,发现A依赖B ,在下边标注一下方面区分

  • beanName : 所依赖的beanName (B)
  • dependentBeanName 当前要加载的 beanName (A)
/**
	 * Register a dependent bean for the given bean,
	 * to be destroyed before the given bean is destroyed.
	 * @param beanName the name of the bean
	 * @param dependentBeanName the name of the dependent bean
	 */
	 
	public void registerDependentBean(String beanName, String dependentBeanName) {
		String canonicalName = canonicalName(beanName);
		synchronized (this.dependentBeanMap) {
			Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
			// 
			if (dependentBeans == null) {
				dependentBeans = new LinkedHashSet<String>(8);
				// (bean 的依赖关系:dependentBeans 依赖 canonicalName)
			    // 依赖我的
				this.dependentBeanMap.put(canonicalName, dependentBeans);
			}
			dependentBeans.add(dependentBeanName);
		}
		synchronized (this.dependenciesForBeanMap) {
			Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
			if (dependenciesForBean == null) {
				dependenciesForBean = new LinkedHashSet<String>(8);
				// 我依赖的
				this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
			}
			dependenciesForBean.add(canonicalName);
		}
	}

总结Bean的加载过程:

  1. 分析从缓存中获取单例 bean,以及对 bean 的实例中获取对象
  2. 如果从单例缓存中获取 bean,Spring 是怎么加载的呢?所以第二部分是分析 bean 加载,以及 bean 的依赖处理
  3. bean 已经加载了,依赖也处理完毕了,第三部分则分析各个作用域的 bean 初始化过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值