深入理解Spring源码(二)之obtainFreshBeanFactory()方法

这边我们将分析obtainFreshBeanFactory()  BeanFactory的创建以及相关的准备工作!



            //这一步主要作用是将配置文件定义解析成beanDefine 注册到beanFactory中
            //但是这里的bean并没有初始化出来 只是提取配置信息 定义相关的属性
            //将这些信息保存到beanDefineMap中(beanName->beanDefine)对应的map
            //我们将深入进去 仔细看看源码

下面内容大多数解释我放在贴出来的代码中  这里只是引入一个类的走向

       

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// 关闭旧的beanFactory 创建新的beanFactory 并注册
		refreshBeanFactory();
		//返回上面创建的beanFactory对象(注意这里是自己改造的)
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		logger.info("Bean factory for " + getDisplayName() + ": " + beanFactory);
		return beanFactory;
	}

首先我们进入refreshBeanFactory方法 我们找到  AbstractRefreshableApplicationContext  对应的实现类

	@Override
	protected final void refreshBeanFactory() throws BeansException {
		//ApplicationContext 如果已经加载了BeanFactory 则销毁所有的Bean 关闭BeanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory); //核心
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

if (hasBeanFactory()) { destroyBeans();closeBeanFactory()}  首先我们判断是否存在BeanFactory 如果不为空我们就将其销毁 和关闭 

接下来 我们新建一个DefaultListableBeanFactory 的beanFactory 对象 我们进入createBeanFactory()方法

	protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}

这步默认创建DefaultListableBeanFactory 对象 这个时候我们的BeanFactory初步形成  这也将是管理整个bean的核心接口

 beanFactory.setSerializationId(getId()); 设置相应的序列化id

 customizeBeanFactory(beanFactory); 设置对应的属性 1:设置是否可重复定义bean 2设置 可循环依赖 代码如下

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		if (this.allowBeanDefinitionOverriding != null) {
			//是否允许bean定义的覆盖
			// BeanDefinition 的覆盖问题大家也许会碰到,
			// 就是在配置文件中定义 bean 时使用了相同的 id 或 name
			// ,默认情况下,allowBeanDefinitionOverriding 属性为 null,
			// 如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖。
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		if (this.allowCircularReferences != null) {
			//是否允许bean 间的循环依赖
			// A 依赖 B,而 B 依赖 A。或 A 依赖 B,B 依赖 C,而 C 依赖 A
			// 默认情况下,Spring 允许循环依赖,当然如果你在 A 的构造方法中依赖 B,在 B 的构造方法中依赖 A 是不行的。
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}

这些属性 我们后面会用到

下面进入最核心的方法loadBeanDefinitions(beanFactory); 这个方法将开始解析配置 转化为对应的BeanDefinition对象

我们点进去(进入)AbstractXmlApplicationContext下的

	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		// 创建同一个XmlBeanDefinitionReader 见名知意 xml的BeanDefine读取器转换器 也就是将xml文件转化为BeanDefinition
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		// 设置当前环境
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		//这里的setResourceLoader赋值 我们在refresh方法的时候就已经给this赋值
		//且看
		// 		super(parent);
		//		// 将配置文件路径设置给AbstractRefreshableConfigApplicationContext 的        configLocations的属性
		//		setConfigLocations(configLocations); //这个方法就将配置路径赋值了
		//		// 由上面的参数传进refresh为true 下面我们就进入refresh方法 spring初始化全程
		//		if (refresh) {
		//			refresh();
		//		}
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		//下面方法是核心
		loadBeanDefinitions(beanDefinitionReader);
	}

继续进入loadBeanDefinitions(beanDefinitionReader);方法

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		//拿到对应配置文件的地址 对应Resources文件夹下面
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			System.out.println(configLocations);
			reader.loadBeanDefinitions(configLocations);
		}
	}

点进reader.loadBeanDefinitions(configLocations);方法

	@Override
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int count = 0;
		for (String location : locations) {
			count += loadBeanDefinitions(location);
		}
		return count;
	}

继续。。。。这中间有点啰嗦 就不一一贴出来了。。我们一直点到XmlBeanDefinitionReader下面的loadBeanDefinitions方法的具体实现

	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}
			// 用一个 ThreadLocal 来存放所有的配置文件资源
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
            //生成一个输入流
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				//核心 我们点进去
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

进入doLoadBeanDefinitions(inputSource, encodedResource.getResource());

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			//这里我们将资源文件转化为Document对象
			Document doc = doLoadDocument(inputSource, resource);
			//开始注册对应的BeanDefinition 我们继续进去
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (SAXParseException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
		}
		catch (SAXException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"XML document from " + resource + " is invalid", ex);
		}
		catch (ParserConfigurationException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Parser configuration exception parsing XML from " + resource, ex);
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"IOException parsing XML document from " + resource, ex);
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Unexpected exception parsing XML document from " + resource, ex);
		}
	}

 

咋们直接进入DefaultBeanDefinitionDocumentReader 下面的doRegisterBeanDefinitions

	protected void doRegisterBeanDefinitions(Element root) {
		// Any nested <beans> elements will cause recursion in this method. In
		// order to propagate and preserve <beans> default-* attributes correctly,
		// keep track of the current (parent) delegate, which may be null. Create
		// the new (child) delegate with a reference to the parent for fallback purposes,
		// then ultimately reset this.delegate back to its original (parent) reference.
		// this behavior emulates a stack of delegates without actually necessitating one.
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
		//钩子 没有作任何的实现 不理会
		preProcessXml(root);
		// 解析xml 将xml元素转化为BeanDefinition
		parseBeanDefinitions(root, this.delegate);
		//钩子 没有作任何的实现 不理会
		postProcessXml(root);

		this.delegate = parent;
	}

根据上面的解释我们直接进入parseBeanDefinitions(root, this.delegate);

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						//默认的命令空间 如beans bean import  resource alias name会进此方法
						parseDefaultElement(ele, delegate);
					}
					else {
						//其他的元素 如扫包 定时器  都会有对应的handler去处理 可以断点看看
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

因为我们这里只是介绍bean的初始化  那么我们暂时只进parseDefaultElement(ele, delegate);  我们点进去

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {

			
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			//处理import标签
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			//处理alias标签
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			//处理bean标签
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// 处理beans标签
			doRegisterBeanDefinitions(ele);
		}
	}

通过标签元素找到对应的process 这里我们只进入processBeanDefinition(ele, delegate);方法体

	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// xml节点信息转化为BeanDefinitionHolder对象
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			//如果有自定义属性的话 进行相应的解析
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				// 这一步就是注册bean啦
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

 delegate.parseBeanDefinitionElement(ele)方法将节点元素转化为BeanDefinitionHolder 我们进入该方法

	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {

		//<bean id="test" class="com.test.seivice.TestService" ></bean>
		//解析像上面这种配置
		// 获取xml中id对应的值
		String id = ele.getAttribute(ID_ATTRIBUTE);
		// 获取xml中name对应的值
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);


		List<String> aliases = new ArrayList<>();
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isTraceEnabled()) {
				logger.trace("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}
	//核心方法  对bean对应的节点进行属性设置 得到xml中全类名
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) {
				try {
					//如果配置中没有定义name只定义了class name我们默认类名的首字母小写作为id(这里很常用)
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
beanName = this.readerContext.generateBeanName(beanDefinition);
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
					if (logger.isTraceEnabled()) {
						logger.trace("Neither XML 'id' nor 'name' specified - " +
								"using generated bean name [" + beanName + "]");
					}
				}
				catch (Exception ex) {
	error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

这个方法完成了bean对应节点元素的解析 转化为BeanDefinitionHolder元素 包括beanDefinition(包含类名 ),beanName,别名。

beanDefinition主要定义了bean创建时候的一些属性 比如是否懒加载,是否单例等等  用于后期创建对象的判断依据 可以去看看这个类 我们在看法中也会定义对应bean的创建所约定的规则。

创建为对应的一个BeanDefinitionHolder 我们回到上上面processBeanDefinition这个方法

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());在这里我们注册我们转化的BeanDefinitionHolder对象 进入该方法

	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {
		// Register bean definition under primary name.
		//拿到对应的beanName 就是我们前面定义的id的名字
		//<bean id="test" 。。。> 就是这里的test
		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
        // 进一步注册
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
        //如果有别名 同样注册别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

我们看看DefaultListableBeanFactory下面的注册方法

@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		//判断是否重新创建BeanDefinition  如果不为空而且 不是可重复出现的bean则报错(前面已经提到过)
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
	else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
}

		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

在这里我们需要关注一下DefaultListableBeanFactory这个类 至关重要!

 

  1. ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口,我们可以获取多个 Bean,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。
  2. ApplicationContext 继承了 HierarchicalBeanFactory,Hierarchical 单词本身已经能说明问题了,也就是说我们可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。
  3. AutowireCapableBeanFactory 这个名字中的 Autowire 大家都非常熟悉,它就是用来自动装配 Bean 用的,但是仔细看上图,ApplicationContext 并没有继承它,不过不用担心,不使用继承,不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法 getAutowireCapableBeanFactory() 就知道了。
  4. ConfigurableListableBeanFactory 也是一个特殊的接口,看图,特殊之处在于它继承了第二层所有的三个接口,而 ApplicationContext 没有。这点之后会用到。

DefaultListableBeanFactory也是BeanFactory重要实现类 主要是用来管理对应的beanDefinition 我们看看这个类的属性

	/** Map of bean definition objects, keyed by bean name. */
	//注册的类就保存在该map中
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

	/** Map of singleton and non-singleton bean names, keyed by dependency type. */
	private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

	/** Map of singleton-only bean names, keyed by dependency type. */
	private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

	/** List of bean definition names, in registration order. */
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

上面是BeanFactory常用管理容器

我们接着上面的注册看 我们将解析出来的beanDefinition用

    this.beanDefinitionMap.put(beanName, beanDefinition);装起来  后面我们通过getBean(beanName)就是获得对应beanDefinition 获取类名 通过一系列的手段创建出对象

到此 我们基本已经完成了将xml中配置的<bean id="test" class="com.test.seivice.TestService" ></bean>(类似)

解析为一个个beanDefinition 放在我们beanDefinitionMap中管理起来  但是我们并未创建对象  创建对象在倒数第二步,不急。。。。

当然 我们在开发中 肯定不会<bean 。。。。/>这样配置很多的这样的内容  一般的都会通过<context:component-scan base-package="XXXX" > 扫包的形式   后面我们会分析通过扫包形成对应的beanDefinition 同样用beanDefinitionMap装起来。

 

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值