`
diecui1202
  • 浏览: 97184 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring 5-从容器中取得bean

阅读更多

三、从容器中取得bean

1、前面体会到了一点,那就是解析bean的职责分工;在这里,这个特点又有充分的体现;
2、如何取得bean?
  1. 当应用程序通过beanFactory.getBean("simpleBean")从容器中取得bean实例时,处理该请求的是AbstractBeanFactory中的以下方法:
protected Object doGetBean(
		final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {

	final String beanName = transformedBeanName(name);
	Object bean = null;

	// 看是否能取到单例对象,这里调用的是DefaultSingletonBeanRegistry的方法
	// DefaultSingletonBeanRegistry负责管理单例的bean,这个我们在后面会谈到
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != 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 + "'");
			}
		}
	    // 这里处理与FactoryBean相关的逻辑
		// 1 如果不是FactoryBean,直接返回
		// 2 如果是FactoryBean,且beanName以&开头,则直接返回FactoryBean
		// 3 如果不是以上两者,则通过factoryBean.getObject()取到工厂生产的bean实例
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}

	else {
		// 如果当前的bean正在创建中,则说明是循环引用,这是不允许的
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		// 如果当前容器中没有该bean的定义信息,则检查父容器中是否存在指定beanName的实例
		// 由上一节可知,DefaultListableBeanFactory主要负责BeanDefinition的注册
		// 这里调用的containsBeanDefinition(beanName)是由DefaultListableBeanFactory实现的
		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 parentBeanFactory.getBean(nameToLookup, args);
			}
			else {
				// No args -> delegate to standard getBean method.
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
		}

		if (!typeCheckOnly) {
			markBeanAsCreated(beanName);
		}

		// 取得合并后的beanDefinition信息,然后cache起来
		final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		checkMergedBeanDefinition(mbd, beanName, args);

		// depend-on属性定义的前置bean,就是在这里创建的,看下面调用了getBean方法
		String[] dependsOn = mbd.getDependsOn();
		if (dependsOn != null) {
			for (int i = 0; i < dependsOn.length; i++) {
				String dependsOnBean = dependsOn[i];
				getBean(dependsOnBean);
				// 同时注册depend-on的bean与原bean的关系,主要是销毁bean时,要先销毁depend-on的bean
				// 这个功能是由DefaultSingletonBeanRegistry来完成的
				registerDependentBean(dependsOnBean, beanName);
			}
		}

		// 到现在,创建bean的条件都准备好了
		// 如果bean是单例,由DefaultSingletonBeanRegistry来完成单例的创建工作
		if (mbd.isSingleton()) {

			// 这里通过新产生一个ObjectFactory来创建并注册一个单例bean
			sharedInstance = getSingleton(beanName, new ObjectFactory() {
				public Object getObject() throws BeansException {
					try {
					    // 很巧妙地又将创建bean的主动权收回给自己
					    // 虽然最后创建bean的工作还是委托给了专门负责这一块的
						// AbstractAutowireCapableBeanFactory来完成
						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后,又检查一下是否是FactoryBean
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
		}
		// 如果是原型bean
		else if (mbd.isPrototype()) {
			// It's a prototype -> create a new instance.
			Object prototypeInstance = null;
			try {
				// 在创建原型bean前,将beanName放在prototypesCurrentlyInCreation中,避免循环创建
				beforePrototypeCreation(beanName);
				// 由子类AbstractAutowireCapableBeanFactory来完成bean的创建工作
				prototypeInstance = createBean(beanName, mbd, args);
			}
			finally {
				// 创建完成后,清理一下现场
				afterPrototypeCreation(beanName);
			}
			// 同样是检查是否是FactoryBean
			bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
		}
		// 其它类型的bean
		else {
			String scopeName = mbd.getScope();
			final Scope scope = (Scope) this.scopes.get(scopeName);
			if (scope == null) {
				throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
			}
			try {
				// 其它类型的scope,其创建bean的实现方式,和前面创建singleton一样
				Object scopedInstance = scope.get(beanName, new ObjectFactory() {
					public Object getObject() throws BeansException {
						beforePrototypeCreation(beanName);
						try {
							// 由子类AbstractAutowireCapableBeanFactory来完成bean的创建工作
							return createBean(beanName, mbd, args);
						}
						finally {
							afterPrototypeCreation(beanName);
						}
					}
				});
				// 同样是检查是否是FactoryBean
				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);
			}
		}
	}

	// 检查bean的类型是否是继承或实现自requiredType
	if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
		throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
	}
	return bean;
}

 2 代码流程

    1. getBean()一开始就检查单例容器中是否存在指定的bean实例,这是因为容器通过beanName不能确定容器是单例还是原型,如果单例的bean存在,当然是单例优先,这个也没什么异议;
    2. 根据beanName找到对应的BeanDefinition定义,这里还是有一点不太明白的地方,就是getMergedLocalBeanDefinition()这个方法;
    3. 如果是单例,创建并注册到单例容器,这样下次取单例bean时,直接就从上面第一步就取到了;
    4. 如果是原型或其它类型,则直接委托子类创建bean实例;
3、小结
  1. 取得bean的工作,完全是由AbstractBeanFactory来完成的;
  2. 如果是单例的bean,则由其父类DefaultSingletonRegistry来管理;
  3. 不管是单例还是原型或是其它类型的bean,AbstractBeanFactory都把创建bean的工作回收给自己的模板方法,然后交由子类AbstractAutowireCapableBeanFactory专门做这件事情;
  4. 通过这篇解读,可以从中了解到,Rod在写Spring框架时,Spring框架所要完成的几部分工作以及该由哪些类去完成,这些思想已经很到位了;这也可以延伸到工作中:
    1. 作为一件事情的owner或管理者,你既要对你的工作了如指掌,同时还要把工作进行拆分,让团队中的不同角色去完成相对独立的模块;
    2. 软件在进行设计时,要充分考虑系统的模块及其耦合,如果能做到恰如其分的拆分,并行进行模块级别的开发,既会让效率大大提升,同时系统的质量也是令人赞扬的;
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics