`

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活动别名
  • 大小: 20.2 KB
分享到:
评论

相关推荐

    spring2.5.6源码

    rar包内含有spring2.5.6源码,解压即可使用 源代码分析,是一件既痛苦又快乐的事情,看别人写的代码是通过的,但当你能够看明白的时候,相信快乐也会随之而来,为了减少痛苦,更快的带来快乐,在这里希望通过这篇...

    Spring高级之注解驱动开发视频教程

    n 源码分析-AbstractBeanFactory的doGetBean方法 l Spring Aop n 设计模式-代理模式 n 编程思想-AOP思想 n 基础应用-入门案例 n 基础应用-常用注解 n 高级应用-DeclareParents注解 n 高级应用-EnableLoadTimeWeaving...

    Spring加载Bean: AbstractBeanFactory.xmind

    Spring加载Bean: AbstractBeanFactory.xmind

    spring-note:Spring源码中文注释和源码分析

    春天的音符 Spring原始中文注释 BeanFactory接口继承 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean

    spring源码12: spring创建Bean

    在上一节讲到,首先spring在AbstractBeanFactory类中创建了ObjectFactory的对象,并重写了getObject()方法,然后将他传给DefaultSingletonBeanRegistry。此时DefaultSingletonBeanRegistry调用了singletonFactory....

    图解Spring源码之循环依赖

    文章目录准备工作关闭循环依赖开始调试AbstractBeanFactory#doGetBeangetSingleton(String beanName, ObjectFactory singletonFactory)AbstractAutowireCapableBeanFactory#createBean(beanName, mbd, args)...

    java-backend:full-stack-path是一个开源项目的学习笔记仓库,包含源码解析,实战指南和面试技巧,也记录了本人在成为一名全栈工程师路上的所得

    Spring源码解析——AbstractBeanFactory Spring源码解析——AbstractAutowireCapableBeanFactory Spring源码解析——Bean的LifeCycle源码+图解 Spring源码解析——ApplicationContext SpringMVC源码 SpringMVC源码...

    SPRING API 2.0.CHM

    AbstractBeanFactory AbstractBeanFactoryBasedTargetSource AbstractBeanFactoryBasedTargetSourceCreator AbstractBindingResult AbstractCachingLabeledEnumResolver AbstractCachingViewResolver ...

    struts2驱动包

    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton...

    gradleTest:gradleTest

    org.springframework.beans.factory.support.AbstractBeanFactory#createBean多实例创建浅拷贝在引用类型复制的是地址,两个值指向一个地址:如果修改原本值的其中一个变量,另外一个值的变量也会被修改 ...

Global site tag (gtag.js) - Google Analytics