DefaultListableBeanFactory:从上章的第3张图片中可以看出,几个实现类都引用了这个类,XmlBeanFactory继承了这个类,我们来看下这个DefaultListableBeanFactory类:它实现了BeanDefinitionRegistry、ConfigurableListableBeanFactory、AbstractAutowireCapableBeanFactory、Serializable接口,和引用了其他的依赖类;
创建一个IoC容器就要使用DefaultListableBeanFactory这个类:
1、创建配置文件,如beans.xml;
2、创建BeanFactory,都会引用或继承DefaultListableBeanFactory;
3、创建资源加载器,如Resource接口;
4、解析、注入资源配置信息,IoC建立成功,就可以直接使用了;
ApplicationContext:
在spring中,spring已经提供了多种ioc容器,BeanFactory是基本的容器,常用ApplicationContext作为容器。
扩展MessageSource接口,这个接口支持国际化语言;
扩展ResourceLoader接口,ResourceLoader是依赖Resource接口的,获得不同地方的Bean定义资源;
扩展ApplicationEventPublisher接口,在容器中引入事件机制,事件与生命周期结合动态管理Bean;
扩展BeanFactory,使功能更丰富;
以FileSystemXmlApplicationContext作为ApplicationContext的实现类,来详解:
FileSystemXmlApplicationContext的构造方法最终都会调用这个构造方法:
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
//public void setParent(ApplicationContext parent) {this.parent = parent;
setConfigLocations(configLocations);
//处理传来的beans.xml字段,并保存给configLocations[];若为空,默认为ApplicationContext.xml,保存之后供refresh()调用;
if (refresh) {
refresh();
//得到beans.xml的配置文件信息
}
}
super(parent);这个方法在AbstractApplicationContext的构造方法设置;
setConfigLocations在AbstractRefreshableConfigApplicationContext定义
refresh :true / false;
refresh()在AbstractApplicationContext中定义
FileSystemXmlApplicationContext获取资源的方法:
@Override
protected Resource getResourceByPath(String path) {
if (path != null && path.startsWith("/")) {
path = path.substring(1);
}
return new FileSystemResource(path);
}
refresh()方法:
@Override
public void refresh() throws BeansException, IllegalStateException {
//private final Object startupShutdownMonitor = new Object();
synchronized (this.startupShutdownMonitor) {
//获取currenttime,验证属性,设置容器同步
prepareRefresh();
//refreshBeanFactory();销毁已存在的容器,创建新容器,并绑定id,设置同步;getBeanFactory();获得存在的容器
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//配置类加载器,运行处理器,配置依赖属性;
prepareBeanFactory(beanFactory);
try {
//所有的配置资源将被加载,还没有允许注册,但允许注册特殊beanpostprocessors(运行处理器)等在当前的容器中实现。
//注册、指定beanpostprocessors
postProcessBeanFactory(beanFactory);
//调用注册了的beanpostprocessors(运行处理器)
invokeBeanFactoryPostProcessors(beanFactory);
//实例化注册了的beanpostprocessors(运行处理器)
registerBeanPostProcessors(beanFactory);
//初始化MessageSource
initMessageSource();
initApplicationEventMulticaster();
//子类特定加载方法
onRefresh();
//注册事件监听器
registerListeners();
//对容器lazy-init属性进行处理的入口方法
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}catch (BeansException ex) {
destroyBeans();
cancelRefresh(ex);
throw ex;
}}}
$2、refresh()与IoC容器的初始化:
当执行refresh()这个方法时就会启动一个IoC容器,也就是说在new FileSystemXmlApplicationContext(String str)或其他构造方法时(都会调用上面讲到的那个构造方法),都会创启动一个IoC容器;
启动一个IoC就包括BeanDefinition(这里可以把BeanDefinition理解一个beans.xml配置文件)定位,载入和注册;这章的主要内容就是分析:定位、载入和注册;
定位:在上章中讲解了Resource、ResurceLoader如可找到一个配置文件(相对路径、绝对路径、URL路径、字节数组),
载入:通过定位读取到了这些配置文件,比如定义了一个<bean id='skx' class='org.skx.api'><property name='name' value='skx'/></bean>,根据这样的配置去执行它所表示的意思;
注册:注册时通过BeanDefinitionRegistry接口完成的,本章开头部分讲过,IoC具体实现类都引用或继承了DefaultListableBeanFactory类,而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,所以,所以实现类都能通过BeanDefinitionRegistry接口完成注册;
FileSystemXmlApplicationContext继承AbstractXmlApplicationContext;在这个父类的loadBeanDefinitions()方法:
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//初始化读取器
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//设置读取器
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//启动、加载读取器
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
最后执行了loadBeanDefinitions(beanDefinitionReader);
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//这个getConfigResources()方法就是与构造器中的setConfigLocations(configLocations)对应
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
这里最后执行的是 reader.loadBeanDefinitions(configLocations);参数是Resource或String:
AbstractBeanDefinitionReader.
@Override
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;
}
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
最后:XmlBeanDefinitionReader. 继承 AbstractBeanDefinitionReader.
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
doLoadDocument(inputSource, resource);
registerBeanDefinitions(doc, resource);
这个loadBeanDefinitions()方法 从beanFactory到reader到resource再到encodeResource 重载了几次,完成对容器的资源文件定位、加载
上个方法中的最后一步:
如何将这些(个)资源文件进行解析和转换为容器数据的,这个过程由XmlBeanDefinitionReader.registerBeanDefinitions(doc,resource)完成;
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//documentReader 将完成对资源文件的解析,
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); //BeanDefinitionDocumentReader
documentReader.setEnvironment(this.getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
图1.

图2.这里所说的document对象是指文档对象,包括doc、xml、html,BeanDefinitionParserDelegate负责解析

图3.documentReader是将得到的document对象按照spring的Bean规则进行解析,解析之后的结果由BeanDefinitionHolder对象持有;

接着上面的
XmlBeanDefinitionReader.registerBeanDefinitions() {BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();方法:
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass)); //类型转换--->父接口
}
private Class<?> documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
再来看DefaultBeanDefinitionDocumentReader.processBeanDefinition()方法:
//ele对应在Spring BeanDefinition中定义的XML元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//通过spring规则解析,bdHolder 获得解析后的结果
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//bdHolder持有这些数据,在内存中,
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex);
}
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);的代码清单:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
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.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("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></bean>元素信息:id、name、aliase等,把这些元素值读出来设置到BeanDefinitionHoler中去;对于其他配置,如bean的属性配置,通过一个较为复杂的解析过程完成,但解析完成后一并放入BeanDefinitionHoler中;返回一
个BeanDefinitionHoler实例;
在AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);这个方法里:就是对BeanDefinition数据分析和载入的过程
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
parseConstructorArgElements(ele, bd);
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));

- 大小: 385.3 KB

- 大小: 64.5 KB

- 大小: 301.6 KB
分享到:
相关推荐
《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》这本书主要聚焦于Spring框架的核心架构和技术细节,帮助读者全面理解Spring的工作机制、设计理念以及实现方式。下面将根据书名及其描述来展开相关知识点。 ...
在深入解析Spring技术内幕第2版中,会详细探讨Spring框架的核心架构与设计原理,Spring作为一个轻量级的Java平台,提供了全面的编程和配置模型,是企业级Java应用程序开发中广泛使用的技术之一。 Spring的核心特性...
《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》从源代码的角度对Spring的内核和各个主要功能模块的架构、设计和实现原理进行了深入剖析。你不仅能从本书中参透Spring框架的出色架构和设计思想,还能从...
Spring技术内幕:深入解析Spring架构与设计原理 Spring是Java企业应用开发的主要框架之一,其架构和设计原理对Java开发者具有重要影响。本文将深入解析Spring架构和设计原理,对Spring的核心概念、架构设计和关键...
Spring技术内幕:深入解析Spring架构与设计原理 Spring技术内幕 Spring是一个基于Java的开源框架,旨在简化Java企业应用的开发。Spring的目标是提供一个简洁、灵活、可扩展的框架,以帮助开发者快速构建企业级...
SPRING技术内幕:深入解析SPRING架构与设计原理SPRING技术内幕:深入解析SPRING架构与设计原理SPRING技术内幕:深入解析SPRING架构与设计原理SPRING技术内幕:深入解析SPRING架构与设计原理SPRING技术内幕:深入解析...
Spring技术内幕 深入解析Spring架构与设计原理1(完整清晰版),一共两部分,这是第一部分 《Spring技术内幕:深入解析Spring架构与设计原理》是Spring领域的问鼎之作,由业界拥有10余年开发经验的资深Java专家亲自...
本书从源代码的角度对Spring的内核和各个主要功能模块的架构、设计和实现原理进行了深入剖析。你不仅能从本书中参透Spring框架的优秀架构和设计思想,还能从Spring优雅的实现源码中一窥Java语言的精髓。本书在开篇...
Spring技术内幕 深入解析Spring架构与设计原理3(完整清晰版),你懂的。下载后请您回复支持一下。
《深入解析Spring MVCgn Web Flow》还介绍了Spring 框架的设计模式,以及如何将同样的设计和技术应用到读者自己的代码中。 《深入解析Spring MVCgn Web Flow》适合各层次Spring Web 程序员阅读。 编辑推荐 《深入...
Spring技术内幕-深入解析Spring架构与设计原理.pdf
### Spring技术内幕与深入解析Spring架构与设计 #### 书籍概述 本书《Spring技术内幕+深入解析Spring架构与设计》是一本专为Spring框架开发者所撰写的深度技术指南。作者凭借超过十年的Java开发经验,从Spring 3.0...
Spring技术内幕:深入解析Spring架构与设计原理(第2部分) 《Spring技术内幕:深入解析Spring架构与设计原理》是Spring领域的问鼎之作,由业界拥有10余年开发经验的资深Java专家亲自执笔!Java开发者社区和Spring...
SPRING技术内幕__深入解析SPRING架构与设计原理,目前csdn上有多分,有的不好使,有的拆成很多分且下载分数很多,这是见过的一本不错的spring书籍,上传共享之、方便下载