spring4.0源码分析━━━(AbstractBeanFactory类分析)



            AbstractBeanFactory在Spring中占着重要的作用,起着一个承上启下的作用。其中最重要的就是getBean方法了,就是从IOC容器中得到Bean都是在本类启动。其类图结构如下:

 

 

 这里通过讲解其中重要的几个方法了解spring中BeanFactory的实现。

  • getMergedLocalBeanDefinition(String beanName)方法:通过beanName得到最有的BeanDefinition。得到BeanDefinition是实例化bean的先决条件。可以看到AbstractAutowireCapableBeanFacory继承了这个AbstractBeanFactory类,而DefaultListableBeanFacotry类又基础了AbstractAutowireCapableBeanFacory。前面一篇解析xml的时候有说过解析完xml后会把BeanDefinition放在DefaultListableBeanFactory类中。所以AbstractBeanFactory类几乎可以得到DefaultListableBeanFactory中的所有属性。这里可能读者会很奇怪,为什么父类反而可以访问子类的属性呢。其实不然像我们初始化IOC容器的时候最简单的就是XmlBeanFactory,而XmlBeanFactory当然就可以访问到父类中所有可以访问到的方法和属性。spring在这其中是使用了大量的模版方法。例如在AbstractBeanFactory中有一个重要的方法,通过beanname得到BeanDefinition。
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName)
			throws BeansException {
		// Quick check on the concurrent map first, with minimal locking.
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null) {
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

.......

protected abstract BeanDefinition getBeanDefinition(String beanName)
			throws BeansException;

 

这里的getBeanDefinition在AbstractBeanFactory为抽象方法,可以相当BeanDefinition在解析xml的时候是向DefaultListableBeanFactory添加的。所以可以猜测getBeanDefinition应该是DefaultListableBeanFactory类中实现的,看一下果然有一个这样的方法。并且这里得到的BeanDefinition是从beanDefinitionMap中得到,至于beanDefinitionMap是怎么初始化这些beanDefinition,可以参考我前面讲解的解析xml分析。

public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
		if (bd == null) {
			if (this.logger.isTraceEnabled()) {
				this.logger.trace("No bean named '" + beanName + "' found in " + this);
			}
			throw new NoSuchBeanDefinitionException(beanName);
		}
		return bd;
}

 

  • getTpye(String beanName)方法:通过beanName得到他对应的class。得到对应的class有什么作用呢,我们知道通过class,然后使用java的反射可以得到很多的东西,包括构造函数,成员变量和方法,甚至annotation。而其中得到构造方法在实例化bean如果发现auto-wire为构造函数时就是从这里获得。特别是AOP中,AOP的实现就是spring会内置一些bean,而这些bean都是通过构造方式实例化的。而不是默认的构造函数实例化然后设置一些属性。方法本身很简单。因为在BeanDefinition中解析xml的时候是有class属性的,也就是直接从BeanDefinition得到class属性。虽然其中这个方法调用过来,调用过去的。但是最终就是从BeanDefinition获得classs属性。
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
		String beanName = transformedBeanName(name);

		// Check manually registered singletons.
		Object beanInstance = getSingleton(beanName, false);
		if (beanInstance != null) {
			if (beanInstance instanceof FactoryBean
					&& !BeanFactoryUtils.isFactoryDereference(name)) {
				return getTypeForFactoryBean((FactoryBean) beanInstance);
			} else {
				return beanInstance.getClass();
			}
		} else if (containsSingleton(beanName)
				&& !containsBeanDefinition(beanName)) {
			// null instance registered
			return null;
		}

		else {
			// No singleton instance found -> check bean definition.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// No bean definition found in this factory -> delegate to
				// parent.
				return parentBeanFactory.getType(originalBeanName(name));
			}

			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

			// Check decorated bean definition, if any: We assume it'll be
			// easier
			// to determine the decorated bean's type than the proxy's type.
			BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
			if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) {
				RootBeanDefinition tbd = getMergedBeanDefinition(
						dbd.getBeanName(), dbd.getBeanDefinition(), mbd);
				Class targetClass = predictBeanType(dbd.getBeanName(), tbd);
				if (targetClass != null
						&& !FactoryBean.class.isAssignableFrom(targetClass)) {
					return targetClass;
				}
			}

			Class beanClass = predictBeanType(beanName, mbd);

			// Check bean class whether we're dealing with a FactoryBean.
			if (beanClass != null
					&& FactoryBean.class.isAssignableFrom(beanClass)) {
				if (!BeanFactoryUtils.isFactoryDereference(name)) {
					// If it's a FactoryBean, we want to look at what it
					// creates, not at the factory class.
					return getTypeForFactoryBean(beanName, mbd);
				} else {
					return beanClass;
				}
			} else {
				return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass
						: null);
			}
		}
}
  • getBean(String name):这个就是最重要的方法了。任何通过getBean就都是调用这个方法了。这个方法也是最为复杂的。
public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(final String name, final Class<T> requiredType,
			final Object[] args, boolean typeCheckOnly) throws BeansException {

		final 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.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);
		}

		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 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);
				}
			}

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

			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);

			// Guarantee initialization of beans that the current bean depends
			// on.
			String[] dependsOn = mbd.getDependsOn();
			if (dependsOn != null) {
				for (String dependsOnBean : dependsOn) {
					getBean(dependsOnBean);
					registerDependentBean(dependsOnBean, beanName);
				}
			}

			// Create bean instance.
			if (mbd.isSingleton()) {
				sharedInstance = getSingleton(beanName, new ObjectFactory() {
					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() {
								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);
				}
			}
		}

		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && bean != null
				&& !requiredType.isAssignableFrom(bean.getClass())) {
			throw new BeanNotOfRequiredTypeException(name, requiredType,
					bean.getClass());
		}
		return (T) bean;
}

protected abstract Object createBean(String beanName,
   RootBeanDefinition mbd, Object[] args) throws BeanCreationException;

可以看到getBean方法又调用的本身的doGetBean方法。在doGetBean中如果是第二次调用,并且bean是单例的那就直接缓存中取了。如果是第一次,流程就比较的复杂了。但是可以想到,肯定是先要得到BeanDefinition,如上标红的代码。可以看到先是检测本身的BeanFactory有没有这个bean,如果没有就从双亲中查询。如果还没有查到就一直向上找。还有如果设置了依赖会先检测依赖。最后就是在getSingleton中通过其中的参数ObjectFactory回调其中的createBean(beanName, mbd, args)方法。这里又使用了模版设计模式,这里的createBean方法是在子类AbstractAutowireCapableBeanFactory实现的。这个会在下次讲解。

  • containsBean:判断当前IOC容器是否包含了指定name的bean
  • isSingleton(String name):根据name判断bean是否单例
  • isPrototype(String name:根据name判断bean是否为prototype
  • isTypeMatch(String name, Class targetType):根据name和class类型判断bean是否为指定的class类型
  • getAliases(String name):根据name活动别名


            AbstractBeanFactory在Spring中占着重要的作用,起着一个承上启下的作用。其中最重要的就是getBean方法了,就是从IOC容器中得到Bean都是在本类启动。其类图结构如下:      这里通过讲解其中重要的几个方法了解spring中BeanFactory的实现。
  • getMergedLocalBeanDefinition(String beanName)方法:通过beanName得到最有的BeanDefinition。得到BeanDefinition是实例化bean的先决条件。可以看到AbstractAutowireCapableBeanFacory继承了这个AbstractBeanFactory类,而DefaultListableBeanFacotry类又基础了AbstractAutowireCapableBeanFacory。前面一篇解析xml的时候有说过解析完xml后会把BeanDefinition放在DefaultListableBeanFactory类中。所以AbstractBeanFactory类几乎可以得到DefaultListableBeanFactory中的所有属性。这里可能读者会很奇怪,为什么父类反而可以访问子类的属性呢。其实不然像我们初始化IOC容器的时候最简单的就是XmlBeanFactory,而XmlBeanFactory当然就可以访问到父类中所有可以访问到的方法和属性。spring在这其中是使用了大量的模版方法。例如在AbstractBeanFactory中有一个重要的方法,通过beanname得到BeanDefinition。
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName)
			throws BeansException {
		// Quick check on the concurrent map first, with minimal locking.
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null) {
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

.......

protected abstract BeanDefinition getBeanDefinition(String beanName)
			throws BeansException;
  这里的getBeanDefinition在AbstractBeanFactory为抽象方法,可以相当BeanDefinition在解析xml的时候是向DefaultListableBeanFactory添加的。所以可以猜测getBeanDefinition应该是DefaultListableBeanFactory类中实现的,看一下果然有一个这样的方法。并且这里得到的BeanDefinition是从beanDefinitionMap中得到,至于beanDefinitionMap是怎么初始化这些beanDefinition,可以参考我前面讲解的解析xml分析。
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
		if (bd == null) {
			if (this.logger.isTraceEnabled()) {
				this.logger.trace("No bean named '" + beanName + "' found in " + this);
			}
			throw new NoSuchBeanDefinitionException(beanName);
		}
		return bd;
}
 
  • getTpye(String beanName)方法:通过beanName得到他对应的class。得到对应的class有什么作用呢,我们知道通过class,然后使用java的反射可以得到很多的东西,包括构造函数,成员变量和方法,甚至annotation。而其中得到构造方法在实例化bean如果发现auto-wire为构造函数时就是从这里获得。特别是AOP中,AOP的实现就是spring会内置一些bean,而这些bean都是通过构造方式实例化的。而不是默认的构造函数实例化然后设置一些属性。方法本身很简单。因为在BeanDefinition中解析xml的时候是有class属性的,也就是直接从BeanDefinition得到class属性。虽然其中这个方法调用过来,调用过去的。但是最终就是从BeanDefinition获得classs属性。

猜你喜欢

转载自992012.iteye.com/blog/1915980