题外话
最近打算读读spring的源码,打算深入学习下spring的IOC,AOP的思想,先找个spring的bean加载研究下。本文使用的spring源码是4.0.0的版本。
入门程序
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
User user = ac.getBean("user", User.class);
System.out.println(user.getUsername());
}
说明:第一行获取classpath下的配置文件spring.xml,然后加载所有的类;第二行获取指定的user的Bean。
源码分析
1. 设置资源的加载setConfigLocations
ClassPathXmlApplicationContext类图
ClassPathXmlApplicationContext类图.jpg
ClassPathXmlApplicationContext属性表
ClasspathXmlApplicationContext属性表.png
ClassPathXmlApplicationContext构造方法
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
// 设置ApplicationContext为null
super(parent);
// 将配置文件的路径存放到字符串数组中
setConfigLocations(configLocations);
if (refresh) {
// 核心方法:刷新spring的上下文
refresh();
}
}
public void setConfigLocations(String... locations) {
// 如果locations数组不为null
if (locations != null) {
// 判断数组路径不为null
Assert.noNullElements(locations, "Config locations must not be null");
// configLocations开辟空间
this.configLocations = new String[locations.length];
// 遍历,然后为configLocations数组赋值
for (int i = 0; i < locations.length; i++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
流程说明:
① super(parent);方法
设置父级上下文ApplicationContext,设置值为null。
② setConfigLocations(configLocations);
将配置文件的路径存放到字符串数组中,初始化configLocations 数组;解析给定的路径,使用properties中的属性替换占位符位置的属性值;而且我们也可以传入多个xml配置文件,使用逗号分隔。
③ refresh();
这个方法是spring加载bean的核心方法,作用就是刷新spring的上下文。
2. AbstractApplicationContext类之refresh方法刷新整个spring上下文
2.1 refresh()方法:刷新整个spring的上下文,完成整个spring上下文的加载
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
//子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//为BeanFactory配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
//为容器的某些子类指定特殊的BeanPost事件处理器
postProcessBeanFactory(beanFactory);
//调用所有注册的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
//为BeanFactory注册BeanPost事件处理器.
//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
//初始化信息源,和国际化相关.
initMessageSource();
//初始化容器事件传播器.
initApplicationEventMulticaster();
//调用子类的某些特殊Bean初始化方法
onRefresh();
//为事件传播器注册事件监听器.
registerListeners();
//初始化所有剩余的单态Bean.
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
//销毁以创建的单态Bean
destroyBeans();
//取消refresh操作,重置容器的同步标识.
cancelRefresh(ex);
throw ex;
}
}
}
2.2 prepareRefresh()方法:准备为spring的上下文刷新
protected void prepareRefresh() {
// 初始化spring上下文开始时间
this.startupDate = System.currentTimeMillis();
// spring上下文关闭的标志
this.closed.set(false);
// spring上下文有效的标志
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 初始化占位符资源
initPropertySources();
// 验证properties中的属性
getEnvironment().validateRequiredProperties();
// 初始化最早应用事件
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
2.3 obtainFreshBeanFactory()方法:告诉子类刷新内部bean工厂
Bean资源文件从这步才开始真正的载入,通过refreshBeanFactory方法实现的。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新Bean工厂
refreshBeanFactory();
// 获取bean工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
// 返回bean工厂
return beanFactory;
}
3. AbstractRefreshableApplicationContext类之refreshBeanFactory方法实现刷新bean工厂
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果beanFactory不为null
if (hasBeanFactory()) {
// 1. 获取beanFactory;如果为null,就抛出IllegalStateException.
// 2. 销毁bean
destroyBeans();
// 关闭beanFactory,将序列号设置为null,将beanFactory设置为null
closeBeanFactory();
}
try {
// 创建父级别的DefaultListableBeanFactory(真正的IOC容器)
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 将beanFactory设置序列化id
beanFactory.setSerializationId(getId());
// 自定义上下文使用的工厂beanFactory(主要是定制化自动装配等配置)
customizeBeanFactory(beanFactory);
// 使用XmlBeanDefinitionReader加载bean
loadBeanDefinitions(beanFactory);
// 初始化beanFactory
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
流程说明:
① 首先判断BeanFactory工厂是否已经创建,如果已经创建那么就销毁关闭BeanFactory工厂。(可以发现spring每次都是建立新的IOC容器)
② 创建DefaultListableBeanFactory真正的ioc容器。
③ 调用loadBeanDefinitions方法加载Bean,实际使用XmlBeanDefinitionReader类操作的。
4. AbstractXmlApplicationContext类之loadBeanDefinitions方法读取Bean定义的资源
// 使用XmlBeanDefinitionReader加载Bean
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 通过BeanFactory来创建一个新的XmlBeanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 设置资源加载的环境
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 设置资源加载器,而容器本身就是一个资源加载器
beanDefinitionReader.setResourceLoader(this);
// 设置schema、dtd解析器
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
initBeanDefinitionReader(beanDefinitionReader);
// Bean加载器真正加载Bean的方法
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 获取配置文件的路径存放到字符串数组
Resource[] configResources = getConfigResources();
// 如果该资源对象数组不为null
if (configResources != null) {
// 使用AbstractBeanDefinitionReader读取定位的Bean定义资源
reader.loadBeanDefinitions(configResources);
}
// 获取ClassPathXmlApplicationContext类中setConfigLocations方法设置的资源路径的数组
String[] configLocations = getConfigLocations();
// 如果资源路径数组不为null
if (configLocations != null) {
// 使用AbstractBeanDefinitionReader读取定位的Bean定义资源
reader.loadBeanDefinitions(configLocations);
}
}
@Override
protected Resource[] getConfigResources() {
return this.configResources;
}
5. AbstractBeanDefinitionReader类之loadBeanDefinitions方法读取Bean定义的资源
XmlBeanDefinitionReader.png// 通过资源路径数组来加载Bean
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
// 计数值(加载次数)
int counter = 0;
// 遍历资源路径数组
for (String location : locations) {
counter += loadBeanDefinitions(location);
}
return counter;
}
// 通过单个资源路径来加载Bean
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
// 从指定的资源位置加载bean
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 获取资源加载器(根据给定的资源文件地址返回对应的Resource)
ResourceLoader resourceLoader = getResourceLoader();
// 如果资源加载器为空就抛出异常
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// 将资源文件路径解析为Spring容器支持的资源对象Resource数组
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 最终还是委派给XmlBeanDefinitionReader来加载资源Resource
// 返回加载次数
int loadCount = loadBeanDefinitions(resources);
// 如果实际资源不为空,将资源添加进去
// 而传入的集合为null
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// 通过URL方式加载资源
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean defintions from location [" + location + "]");
}
return loadCount;
}
}
6. XmlBeanDefinitionReader类之loadBeanDefinitions方法读取Bean定义的资源
// 通过资源对象Resource数组加载Bean
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
// 计数值
int counter = 0;
// 遍历资源对象Resource数组
for (Resource resource : resources) {
counter += loadBeanDefinitions(resource);
}
return counter;
}
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 将资源Resource包装成特殊编码的EncodedResource
return loadBeanDefinitions(new EncodedResource(resource));
}
// XmlBeanDefinitionReader读取Bean定义的资源
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 {
// 定义输入源,设置了资源文件xml的字节输入流
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();
}
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 使用配置的文档来加载程序和加载指定文档
// 将Resource资源(XML文件)转换为Document独享,而解析加载过程使用了documentLoader实现
Document doc = doLoadDocument(inputSource, resource);
// 对Bean定义解析
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);
}
}
// 使用配置的文档来加载程序和加载指定文档
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
7. DocumentLoader将Bean定义的资源转换为Document对象
// 使用JAXP来解析XML文档为Document对象
@Override
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
// 创建文档解析工厂
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if (logger.isDebugEnabled()) {
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
}
// 创建文档解析器
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
// 解析Bean定义的资源
return builder.parse(inputSource);
}
// 创建DocumentBuilderFactory工厂实例
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
throws ParserConfigurationException {
// 创建文档解析工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(namespaceAware);
// 设置文档校验模型,validationMode不为0
if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
// 设置校验为true
factory.setValidating(true);
// 如果文档校验模型为XSD校验
if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
// Enforce namespace aware for XSD...
factory.setNamespaceAware(true);
try {
// SCHEMA_LANGUAGE_ATTRIBUTE 使用JAXP属性配置验证的语言
// XSD_SCHEMA_LANGUAGE XSD模式语言的JAXP属性值
factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
}
catch (IllegalArgumentException ex) {
ParserConfigurationException pcex = new ParserConfigurationException(
"Unable to validate using XSD: Your JAXP provider [" + factory +
"] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " +
"Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
pcex.initCause(ex);
throw pcex;
}
}
}
return factory;
}
// 使用JAXP创建一个文档解析器DocumentBuilder,用于解析XML文档
protected DocumentBuilder createDocumentBuilder(
DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler)
throws ParserConfigurationException {
// 通过工厂创建文档解析器
DocumentBuilder docBuilder = factory.newDocumentBuilder();
if (entityResolver != null) {
docBuilder.setEntityResolver(entityResolver);
}
if (errorHandler != null) {
docBuilder.setErrorHandler(errorHandler);
}
return docBuilder;
}
8. XmlBeanDefinitionReader类之registerBeanDefinitions方法解析Document中的Bean定义
// 解析DOM文档Document中包含的Bean定义
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 创建BeanDefinitionDocumentReader用来解析Document
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 获取容器中注册的Bean的数量
int countBefore = getRegistry().getBeanDefinitionCount();
// 此处委派给了DefaultBeanDefinitionDocumentReader来实现Bean定义的解析
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回解析的Bean数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
// 创建一个BeanDefinitionDocumentReader用来解析Document
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
// 使用构造器通过反射来创建对象,强制类型转换为BeanDefinitionDocumentReader类型
return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
9. DefaultBeanDefinitionDocumentReader类之registerBeanDefinitions方法解析Document中的Bean定义
// 根据spring-beans的XSD文件来解析bean的定义
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
// 初始化XML描述符
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
// 获取document的根元素
Element root = doc.getDocumentElement();
// 在给定的根元素root的内部注册每个Bean的定义
doRegisterBeanDefinitions(root);
}
// 在给定的根元素的内部注册每个Bean的定义
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用于完成真正的解析过程
BeanDefinitionParserDelegate parent = this.delegate;
// 对BeanDefinitionParserDelegate进行初始化
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);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
// 在解析Bean定义之前,扩展解析自定义配置
preProcessXml(root);
// 从Document的根元素root开始进行Bean定义的Document对象
parseBeanDefinitions(root, this.delegate);
// 在解析Bean定义之后,扩展解析自定义配置
postProcessXml(root);
this.delegate = parent;
}
// 对BeanDefinitionParserDelegate进行初始化
protected BeanDefinitionParserDelegate createDelegate(
XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
// 创建BeanDefinitionParserDelegate
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
// 初始化Document的根元素
// 通过给定的根元素初始化DocumentDefaultsDefinition类
delegate.initDefaults(root, parentDelegate);
return delegate;
}
// 解析文档中的根级别元素(import标签,alias标签,bean标签,beans元素)
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// Bean定义的document对象使用spring的默认xml命名空间
if (delegate.isDefaultNamespace(root)) {
// 获取bean根元素下的所有子节点
NodeList nl = root.getChildNodes();
// 遍历所有子节点
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 判断节点是否为Element元素节点
if (node instanceof Element) {
// 将节点node强制类型转为Element元素
Element ele = (Element) node;
// 使用Spring的Bean规则解析元素节点
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {// 使用用户自定义的命名空间解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 根节点没有使用spring的默认命名空间,就使用用户自定义的命名空间解析
delegate.parseCustomElement(root);
}
}
10. DefaultBeanDefinitionDocumentReader类之解析<import>,<alias>,<bean>,<beans>元素
// 解析Document元素Element节点
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 如果元素节点是<import>节点
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
// 解析Document元素中的<import>节点
importBeanDefinitionResource(ele);
}
// 如果元素节点是<alias>节点
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
// 解析Document元素中的<alias>节点
processAliasRegistration(ele);
}
// 如果元素节点是<bean>节点
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
// 解析Document元素中的<bean>节点
processBeanDefinition(ele, delegate);
}
// 如果元素节点是<beans>节点
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 解析Document元素中的<beans>节点
doRegisterBeanDefinitions(ele);
}
}
11. DefaultBeanDefinitionDocumentReader类之真正解析<import>元素
// 解析<import>节点元素并且将bean定义从给定资源中加载到bean工厂
protected void importBeanDefinitionResource(Element ele) {
// 获取导入资源的location属性
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
// 如果location属性值为空,那么直接返回
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
// 使用系统变量值来解析location属性值
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<Resource>(4);
// 判断location属性值的定位是否为绝对路径
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}
catch (URISyntaxException ex) {
// cannot convert to an URI, considering the location relative
// unless it is the well-known Spring prefix "classpath*:"
}
// 如果location定位为绝对路径
if (absoluteLocation) {
try {
// 通过指定路径加载bean定义的资源,返回<import>节点的加载次数
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}
else {// 否则location定位按照相对路径处理
try {
int importCount;
// 通过指定路径获取相对路径下的资源Resource
Resource relativeResource = getReaderContext().getResource().createRelative(location);
// 判断相对路径对应的资源是否存在
if (relativeResource.exists()) {
// 使用XmlBeanDefinitionReader读取相对路径下的资源
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
else {
String baseLocation = getReaderContext().getResource().getURL().toString();
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
ele, ex);
}
}
Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
// 在解析完<Import>元素之后,发送容器导入其他资源处理完成事件
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
12. DefaultBeanDefinitionDocumentReader类之真正解析<bean>元素
// 解析Document元素中的<bean>节点
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder类对BeanDefinition的封装
// 使用BeanDefinitionParserDelegate解析文档Document中的<bean>元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// IOC容器注册BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
//在完成向Spring IoC容器注册解析得到的Bean定义之后,发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
// 解析提供的Bean元素
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
// 解析提供的Bean元素
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// 获取bean元素中的id属性
// public static final String ID_ATTRIBUTE = "id";
String id = ele.getAttribute(ID_ATTRIBUTE);
// 获取bean元素中的name属性
// public static final String NAME_ATTRIBUTE = "name";
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
// 将bean元素中name属性值存放到别名中
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
// 如果bean设置了id,那么将id作为beanName
// 如果别名集合不为空,那么将别名集合的第一个元素作为beanName
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) {
// 检查Bean元素配置的id、name或者别名是否重复
checkNameUniqueness(beanName, aliases, ele);
}
// 解析bean定义本身,而不考虑名称或别名。
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
// 如果bean元素没有配置id、别名或者name并且没有包含子Bean元素
// 那么就解析Bean生成唯一beanName并注册
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 如果bean元素没有配置id、别名或者name并且包含子Bean元素
// 那么就解析Bean使用别名注册
beanName = this.readerContext.generateBeanName(beanDefinition);
// 为了保持对于Spring 1.2/2.0向后兼容性
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定义本身,而不考虑id、名称、别名(上面已经处理过了)
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
// 专门记录解析的Bean元素
this.parseState.push(new BeanEntry(beanName));
String className = null;
// 获取bean元素中的class属性
// public static final String CLASS_ATTRIBUTE = "class";
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
// 获取bean元素中的parent属性
// public static final String PARENT_ATTRIBUTE = "parent";
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 为Bean元素配置的class名称和parent属性值创建BeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 对当前的Bean元素中配置的一些属性进行解析和设置,如配置的单态(singleton)属性等
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
// 为Bean元素解析的Bean设置description信息
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 对Bean元素的meta(元信息)属性解析
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析Bean元素的构造方法设置
parseConstructorArgElements(ele, bd);
// 解析Bean元素的property属性
parsePropertyElements(ele, bd);
// 解析Bean元素的qualifier属性
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
13. BeanDefinitionParserDelegate类之真正解析<property>元素
// 解析Property元素及其子元素
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
// 获取bean元素中的子元素
NodeList nl = beanEle.getChildNodes();
// 遍历子元素节点
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 判断子元素是否<property>子元素
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
// 调用解析<property>子元素方法解析
parsePropertyElement((Element) node, bd);
}
}
}
// 解析Property元素
public void parsePropertyElement(Element ele, BeanDefinition bd) {
// 获取property元素中的name属性
// public static final String NAME_ATTRIBUTE = "name";
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
// 校验属性值不为null
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
this.parseState.push(new PropertyEntry(propertyName));
try {
// 判断Bean定义中是否存在这个property元素
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
// 获取property元素的值
// 同时也解析property子元素
Object val = parsePropertyValue(ele, bd, propertyName);
PropertyValue pv = new PropertyValue(propertyName, val);
// 解析property元素中的属性
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
14. BeanDefinitionReaderUtils类之registerBeanDefinition将BeanDefinition在IOC容器中注册
// 将Bean定义注册到Bean工厂
// BeanDefinitionHolder包括了BeanDefinition和bean的别名
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
// 获取Bean定义的名称
String beanName = definitionHolder.getBeanName();
// 使用Bean名称和BeanDefinition向IOC容器注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
// 如果BeanDefinition有别名,那么向ioc容器注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
15. DefaultListableBeanFactory类之registerBeanDefinition真正注册BeanDefinition
DefaultListableBeanFactory的UML图.png// 使用Bean名称和BeanDefinition向IOC容器注册
@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");
// 校验BeanDefinition;校验方法的注解、方法名称等
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
// 通过beanName获取对应的旧的BeanDefinition
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 检查是否有同名的BeanDefinition已经在IoC容器中注册
if (oldBeanDefinition != null) {
// 如果不允许BeanDefinition重写,那么抛出BeanDefinition存储异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
// 如果新的需要注册的BeanDefinition不等于之前已经注册的BeanDefinition
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
// 进行新的需要注册的BeanDefinition覆盖之前已经注册的BeanDefinition
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
// 设置新的需要注册的BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else { // 之前没有注册过BeanDefinition
if (hasBeanCreationStarted()) {// 如果已经创建BeanDefinition不为空
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
// 设置当前需要注册BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 创建存储更新BeanDefinition的名称的集合
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
// 将之前的BeanDefinition的名称插入到集合中
updatedDefinitions.addAll(this.beanDefinitionNames);
// 将当前的BeanDefinition的名称插入到集合中
updatedDefinitions.add(beanName);
// 设置最新的BeanDefinition的名称集合
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {// 如果已经创建BeanDefinition为空
// 设置beanName对应的beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 将beanName添加到名称集合中
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 重置所有已经注册过的BeanDefinition的缓存
if (oldBeanDefinition != null || containsSingleton(beanName))
resetBeanDefinition(beanName);
}
}
spring初始化核心流程
1. AbstractApplicationContext类的refresh方法刷新spring上下文,完成spring上下文的加载。
2. AbstractXmlApplicationContext类的loadBeanDefinitions方法开始读取Bean定义的资源。
3. loadBeanDefinitions方法的流程:
4. 使用ResourceLoader通过给定的类路径加载资源,spring将资源文件封装成了Resource类,这样就拿到了Resource。
5. 使用XmlBeanDefinitionReader来解析XML资源Resource文件;譬如解决资源编码等问题。
6. 使用DocumentLoader将资源Resource转换为Document文档对象,这样就拿到了Document。
7. 表面上使用XmlBeanDefinitionReader解析Document对象;实际上是委派给BeanDefinitionParserDelegate类完成解析Document对象。
8. 使用DefaultBeanDefinitionDocumentReader类解析Document对象中的<import>,<alias>,<bean>,<beans>元素Element。
9. 将<bean>元素Element通过BeanDefinitionParserDelegate解析为BeanDefinitionHolder;而BeanDefinitionHolder本身是一个BeanDefinition的封装。
10. 如果需要<property>元素,那么需要BeanDefinitionParserDelegate类来解析,解析为BeanDefinition。
11. 最后在DefaultListableBeanFactory类实现了BeanDefinitionRegistry接口,完成BeanDefinition注册。
12. 注册的过程就是实现了一个公共的ConcurrentHashMap类型的beanDefinitionMap来保存刷新spring上下文的BeanDefinition。
到此只是粗略的完成了ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");中spring IOC容器的初始化。
实际上上面的过程还有很多地方可以深究,标签<list>解析,<property>子标签解析,qualifier属性解析等。spring ioc初始化复杂的地方在于它不停的委派给其他类来实现。至于getBean方法完成依赖注入下篇博客分析。
网友评论