- 浏览: 57826 次
- 性别:
- 来自: 成都
文章分类
本篇将介绍下ApplicationContext上下文方式的得到bean的源码
上篇用到一个列子
就从ClassPathXmlApplicationContext入手吧
找到它的构造函数
调用的是上面的这个
里面又调用另一个构造函数
看到setConfigLocations(configLocations);这个方法,在跟进去咯
这里面的关键点是
这里面有个属性configLocations其定义如下
在上面关键代码第一行初始化,然后for语句段就是解析路径的。resolvePath方法就不跟进咯,OK,在回到上上面的构造函数里,解释了setConfigLocations方法,在往下走咯。就来到
由于传进来的refresh参数是true,所以refresh()方法就会执行咯。好吧,上refresh这牛X的方法
这方法的东西好丰富哦,就各点来击破咯
first 这 synchronized (this.startupShutdownMonitor) 都懂得啥下面first的方法是prepareRefresh();这方法可以忽略咯,就是setting its startup date,
second 就是ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这里调用的是父类AbstractRefreshableApplicationContext的方法obtainFreshBeanFactory();
源码如下
这里面又有别的方法调用咯,第一个方法实现
这里面又调用了createBeanFactory(),看方法就明白意思了啥,就是创建BeanFactory.
在回到refreshBeanFactory()方法中,接下来就是调用loadBeanDefinitions(beanFactory),看意思就是加载beanDefinition了,这个方法是在AbstractRefreshableConfigApplicationContext的子类AbstractXmlApplicationContext实现的
这里面创建了一个XmlBeanDefinitionReader 对象,这玩意就是来读取基于XML bean定义的
。而beanDefinitionReader.setResourceLoader(this);这句咯是为reader配置resourceLoader,因为DefaultResourceLoader是父类,所以this可以直接被使用。initBeanDefinitionReader(beanDefinitionReader);是初始化,而loadBeanDefinitions(beanDefinitionReader);类容多了
这里面的有两种方式加载bean咯,一个是Resouce,一个是String,来看下reader.loadBeanDefinitions(configResources);的实现
这里面又调用了 loadBeanDefinitions()这方式的实现是在XmlBeanDefinitionReader中,
这代码的主要意思是,的到xml文件,并得到IO的InputSource.在返回时有句doLoadBeanDefinitions(inputSource, encodedResource.getResource());这发放的源码
这方法就是加载bean定义在制定的XML文件。主要代码是
documentLoader的实例 private DocumentLoader documentLoader = new DefaultDocumentLoader();它主要是取得XML文件Document对象。这里就不在详述了,时间有限咯。
在取得Document对象后,就要开始注册咯registerBeanDefinitions(doc, resource);就由这方法搞定咯
上篇用到一个列子
ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
就从ClassPathXmlApplicationContext入手吧
找到它的构造函数
public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); }
调用的是上面的这个
里面又调用另一个构造函数
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
看到setConfigLocations(configLocations);这个方法,在跟进去咯
public void setConfigLocations(String[] locations) { if (locations != null) { Assert.noNullElements(locations, "Config locations must not be null"); this.configLocations = new String[locations.length]; for (int i = 0; i < locations.length; i++) { this.configLocations[i] = resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }
这里面的关键点是
this.configLocations = new String[locations.length]; for (int i = 0; i < locations.length; i++) { this.configLocations[i] = resolvePath(locations[i]).trim(); }
这里面有个属性configLocations其定义如下
private String[] configLocations;,就是个数组来存放路径的,
在上面关键代码第一行初始化,然后for语句段就是解析路径的。resolvePath方法就不跟进咯,OK,在回到上上面的构造函数里,解释了setConfigLocations方法,在往下走咯。就来到
if (refresh) { refresh(); } }
由于传进来的refresh参数是true,所以refresh()方法就会执行咯。好吧,上refresh这牛X的方法
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
这方法的东西好丰富哦,就各点来击破咯
first 这 synchronized (this.startupShutdownMonitor) 都懂得啥下面first的方法是prepareRefresh();这方法可以忽略咯,就是setting its startup date,
second 就是ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
这里调用的是父类AbstractRefreshableApplicationContext的方法obtainFreshBeanFactory();
源码如下
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
这里面又有别的方法调用咯,第一个方法实现
protected final void refreshBeanFactory() throws BeansException { 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); } }
这里面又调用了createBeanFactory(),看方法就明白意思了啥,就是创建BeanFactory.
protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }
在回到refreshBeanFactory()方法中,接下来就是调用loadBeanDefinitions(beanFactory),看意思就是加载beanDefinition了,这个方法是在AbstractRefreshableConfigApplicationContext的子类AbstractXmlApplicationContext实现的
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. 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); }
这里面创建了一个XmlBeanDefinitionReader 对象,这玩意就是来读取基于XML bean定义的
。而beanDefinitionReader.setResourceLoader(this);这句咯是为reader配置resourceLoader,因为DefaultResourceLoader是父类,所以this可以直接被使用。initBeanDefinitionReader(beanDefinitionReader);是初始化,而loadBeanDefinitions(beanDefinitionReader);类容多了
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
这里面的有两种方式加载bean咯,一个是Resouce,一个是String,来看下reader.loadBeanDefinitions(configResources);的实现
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { Assert.notNull(resources, "Resource array must not be null"); int counter = 0; for (Resource resource : resources) { counter += loadBeanDefinitions(resource); } return counter; }
这里面又调用了 loadBeanDefinitions()这方式的实现是在XmlBeanDefinitionReader中,
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(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.set(null); } } }
这代码的主要意思是,的到xml文件,并得到IO的InputSource.在返回时有句doLoadBeanDefinitions(inputSource, encodedResource.getResource());这发放的源码
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); return registerBeanDefinitions(doc, resource); } 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); } }
这方法就是加载bean定义在制定的XML文件。主要代码是
Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
documentLoader的实例 private DocumentLoader documentLoader = new DefaultDocumentLoader();它主要是取得XML文件Document对象。这里就不在详述了,时间有限咯。
在取得Document对象后,就要开始注册咯registerBeanDefinitions(doc, resource);就由这方法搞定咯
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // Read document based on new BeanDefinitionDocumentReader SPI. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
发表评论
-
Spring源码分析之IOC
2013-03-16 21:40 735先看两种方式在IOC容器取得bean 1 beanFactor ... -
一些在工作中遇到的问题汇总
2012-12-10 23:31 0保留一定的小数位数 1 DecimalFormat ... -
Set集合源码初探
2012-12-06 23:07 0[color=green][size=medium] ... -
一些常用的jar包
2012-12-04 22:44 0一些常用的jar 放在网上方便使用 Did your c ... -
java 获取请求ip
2012-11-20 23:11 3243public class IpUtil { publ ... -
mongodb
2012-11-20 22:09 689mongodb文档, -
padingtoolbar 的扩张
2012-10-31 22:01 0在Ext的原有分页控件中,服务器端方法是根据传入的起始数据记录 ... -
extjs的一些组件
2012-10-17 22:34 670<script type="text/java ... -
extjs
2012-10-14 23:09 611extjs的一些文档 -
jquery ui
2012-09-11 22:54 701一个jquery ui 后台 -
重拾java之线程1
2012-09-10 00:17 908[size=medium] 接触java也有一段时间了,以前选 ... -
dom4j 一些使用
2012-07-30 22:40 0dom4j使用 -
一个http请求
2012-07-18 00:04 0ackage com.sxit.phoenix.common; ... -
读书笔记effective之对所有对象通用的方法
2012-03-18 17:22 858读书笔记effective之对所有对象通用的方法 第一条 覆 ... -
读书笔记effective java 之条目
2012-03-18 15:05 819最近看了下effective java 有编程许多经验值得学 ... -
读书笔记effective java 之通用程序设计3
2012-03-15 22:21 851第五条 基本类型优先于装箱基本类型 java有一个类型系 ... -
读书笔记effective java 之通用程序设计2
2012-03-15 20:59 892第三条 了解和使用类库 ... -
effective java 之通用程序设计
2012-03-15 16:15 741第一条 将局部变量的作用域最小化 将局部变量的作用域最小 ... -
http与socket连接区别
2011-11-08 01:11 446相信不少初学手机联网 ... -
HashMap 一般遍历
2011-11-04 16:28 759Map map=new HashMap() Iterator ...
相关推荐
Spring源码分析_Spring_IOC
Spring源代码解析(二):ioc容器在Web容器中的启动 Spring源代码分析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务处理...
这是spring_ioc部分的内容。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。...
3、源码分析-IOC容器的初始化 4、源码分析-IOC容器的依赖注入 5、源码分析-IOC容器的高级特性 三阶段 Spring AOP的涉及原理及具体实践 SpringJDBC的涉及原理及二次开发 SpringMVC框架设计原理及手写实现 四阶段 ...
spring version: 5.0.0; jdk: 1.8 IOC大致调用顺序(IOC调用的AOP标签解析)
老王读 Spring IoC 系列文章的源码分析&测试代码 Spring IoC 源码分析,帮助大家学习 Spring 源码,更加了解 Spring 的底层 博客专栏地址:https://blog.csdn.net/wang489687009/category_11269905.html
spring5源码分析视频,内容包括源码分析、ioc/aop/事务等等,还有手写spring5框架内容
Spring源代码解析(二):ioc容器在Web容器中的启动 3.Spring源代码解析(三):Spring JDBC 4.Spring源代码解析(四):Spring MVC 5.Spring源代码解析(五):Spring AOP获取Proxy 6. Spring源代码解析(六):Spring...
有关于Spring,我们最常用的两个功能就是IOC和AOP,前几篇文章从源码级别介绍了Spring容器如何为我们生成bean及bean之间的依赖关系 下面我们接着来看AOP的源码实现。 有关于AOP,我们在面试中也被无数次问到...
Spring Ioc源码分析系列--自动注入循环依赖的处理.doc
Spring Ioc源码分析系列--@Autowired注解的实现原理.doc
1. bean的装配方式 1.表明当前类是一个配置类,是方法bean的源 2.将@Configuration配置的AppConfig的BeanDefinitio
本文深入探讨了Spring IoC容器的加载过程及其源码实现,揭示了Spring中最为根本的概念之一。这包括从AnnotationConfigApplicationContext的实例化开始,到DefaultListableBeanFactory工厂的建立,再到...
本文深入探讨了Spring框架中IoC容器的源码机制,涵盖了容器的初始化、Bean工厂的实例化、Bean定义的读取及Spring Bean的生命周期管理。通过精细的分析,本文揭示了AnnotationConfigApplicationContext的实例化过程,...
Spring 源码分析(Bean的初始化) 前言 本篇文章是个人第一次看spring源码并总结,同时也参考了下面这篇博客。基本也是按照他的思路来理解的。这也算是第一版个人简易理解。也算是窥见spring的冰山一角,之后也会...
NULL 博文链接:https://ziyoujiedao.iteye.com/blog/262360
Spring源代码解析(二):ioc容器在Web容器中的启动.doc Spring源代码分析(三):Spring JDBC.doc Spring源代码解析(四):Spring MVC.doc Spring源代码解析(五):Spring AOP获取Proxy.doc Spring源代码解析(六):...
视频详细讲解,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 1、课程简介 Spring框架是一系列应用框架的核心,也可以说是整合其他应用框架的基座。...n 源码分析-TransactionSynchronizationManager