Spring的常用配置文件是applicationContext.xml文件,最简单的,一般我们都会添加这样的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.harvey.demo.*"></context:component-scan>
</beans>
Spring是根据BeanDefinition来创建Bean对象,BeanDefinition就是Spring中表示Bean定义。BeanDefinition用来存储Bean的相关信息,主要包括:Bean的属性、是否单例、延迟加载、Bean的名称、构造方法等。
那Spring是如何找到所有的目标类创建对象的BeanDefinition的呢?
入口是AbstractApplicationContext的refresh方法
//-------- AbstractApplicationContext的refresh方法
// Prepare this context for refreshing.
prepareRefresh();
// Step2:调用子类覆盖的方法obtoinFreshBeanFactory(),创建新的BeanFactory,默认实现是DefaultListableBeanFactory
// 解析xml,生成BeanDefinition并注册到 BeanDefinitionRegistry
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// 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();
在obtainFreshBeanFactory方法中一共是两个方法
- refreshBeanFactory:初始化BeanFactory
- getBeanFactory:返回实例化的BeanFactory
ConfigurableListableBeanFactory#obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
走到refreshBeanFactory()方法内部,核心方法loadBeanDefinitions(),这个方法是读取xml文件读取bean的定义。最后赋值到该类的BeanFactory中。
AbstractRefreshableApplicationContext#refreshBeanFactory{
//如果已经存在BeanFactory,则先销毁先前的BeanFactory,关闭连接以释放资源
if (hasBeanFactory()) {
//销毁先前的BeanFactory
destroyBeans();
//关闭连接
closeBeanFactory();
}
try {
//创建一个新的BeanFactory,在这里使用DefaultListableBeanFactory作为BeanFactory的默认实现类
DefaultListableBeanFactory beanFactory = createBeanFactory();
//设置从ID,用于 BeanFactory 的序列化和反序列化
beanFactory.setSerializationId(getId());
//调用子类的customizeBeanFactory方法,用于在创建新的BeanFactony后,对BeanFactory进行附加的自定义设置
customizeBeanFactory(beanFactory);
/**
* 【重点】加载Bean定义,这个bean definition 是通过XmlBeanDefinitionReader来读取Spring的配置文件(通常为XL格式的〉,得到Bean定义实现类AbstractXmlApplicationContext
*/
loadBeanDefinitions(beanFactory);
//将当前BeanFactory实例赋值给该类实例的beanFactory变量中
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
//如果在解析Bean定义源时遇到I/0错误,则抛出ApplicationContextException异常
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
点击查看这个类下的实现方法。
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 为beanFactory创建XmlBeanDefinitionReader对象
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//用当前 ApplicationContext的环境来配置 BeanDefinition读取器
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//初始化 BeanDefinition 读取器,让子类可以对其进行自定义初始化(留一个可扩展的接口)
initBeanDefinitionReader(beanDefinitionReader);
/**关键方法:读取 BeanDefinition并向 BeanFactory注册*/
loadBeanDefinitions(beanDefinitionReader);
}
然后走到loadBeanDefinitions(),还是调用loadBeanDefinitions()方法。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
//将每一个Resource的 BeanDefinition 读取并注册到BeanDefinitionRegistry 中
reader.loadBeanDefinitions(configResources);
}
//获取要加载的配置文件路径,即ClassPath下的XML配置
String[] configLocations = getConfigLocations();
if (configLocations != null) {
/**
* 关键方法:根据路径加载配置文件中的 BeanDefinition并注册到 BeanFactory 中
*/
reader.loadBeanDefinitions(configLocations);
}
}
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
for (Resource resource : resources) {
/**入口,实现类XmlBeanDefinitionReader.loadBeanDefinitions*/
counter += loadBeanDefinitions(resource);
}
return counter;
}
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<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//把XML读取的文件流,解析成InputSource对象
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
/**入口,spring框架里面真正干活的方法名 doXXX*/
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();
}
}
}
到了这个方法,才开始执行真正的逻辑,通过读取资源载入Bean定义信息。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//读取XML配置,把配置文件转成Document对象
Document doc = doLoadDocument(inputSource, resource);
/**根据解析得到的Document对象,将其中的 Bean配置信息注册到BeanFactory 中*/
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//创建 BeanDefinitionDocumentReader对象,用于读取文档转化成的 Element
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//记录当前注册的 Bean数量
int countBefore = getRegistry().getBeanDefinitionCount();
/**
* 通过BeanDefinitionDocumentReader的实现来对所提供的Document的BeanDefinition进行解析
* 关键方法:registerBeanDefinitions
*/
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//计算当前实际注册的Bean数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
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);
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;
}
}
}
//预处理XNL元素,例如在XML解析之前可以修改XML DOM树,空实现,给子类定义
preProcessXml(root);
/**关键入口:解析Bean定义并注册 Bean 到 BeanFactory 容器中*/
parseBeanDefinitions(root, this.delegate);
//后处理XML元素,例如解析后的 Bean定义可能需要改变XNL DOM树等,空实现,给子类定义
postProcessXml(root);
// 恢复到原先的的 BeanDefinitionParserDelegate 委托对象
this.delegate = parent;
}
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) {
//如果子节点也是元素节点,并且也使用了默认命名空间,则通过默认方式解析元素
//默认的命名空间是:http://www.springframework.org/schema/beans
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//解析bean元素信息
parseDefaultElement(ele, delegate);
}
else {
//如果没有指定默认命名空间,也通过自定义方式解析元素
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
解析xml节点分为两种情况:
- 解析默认命名空间下的元素,即http://www.springframework.org/schema/beans
- 解析非默认命名空间下的元素
首先我们来看看如何解析默认命名空间下的元素
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//解析<import>元素
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//解析<alias>元素
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//解析<bean>元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//关键方法:bean元素处理
processBeanDefinition(ele, delegate);
}
//解析<beans>元素
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
//递归调用doRegisterBeanDefinitions()方法解析并注册嵌套的<beans>元素
doRegisterBeanDefinitions(ele);
}
}
回到前面代码,我们再看看是如何解析非默认命名空间下的元素的
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
//第一步:获取元素的namespaceUri
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//第二步:通过namespaceUri获取对应的NamespaceHandler,
//例如<context>的命名空间处理器就是ContextNamespaceHandler
//在这里会实例化NamespaceHandler,并调用其init方法,创建诸多解析器,其中就有component-scan对应的解析器ComponentScanBeanDefinitionParser
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//第三步:调用NamespaceHandler的parse方法准备开始解析
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
//【NamespaceHandlerSupport】
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//根据元素拿到对应的解析器,比如component-scan对应的解析器ComponentScanBeanDefinitionParser
BeanDefinitionParser parser = findParserForElement(element, parserContext);
//调用对应解析器的parse方法解析
return (parser != null ? parser.parse(element, parserContext) : null);
}
//【ComponentScanBeanDefinitionParser】
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//获取元素的base-package属性值
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
//处理占位符
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
//根据一些自定义配置信息创建扫描器,比如include-filter、exclude-filter等等
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
//找到声明包路径下的组件,并将类信息封装,实例化为BeanDefinitionHolder,并注册到beanDefinitionMap中
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
//注册其他组件,比如一些依赖bean、内部bean
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
整一个创建的流程,就走完啦,从解析xml,到封装成BeanDefinition,最后放入map中的核心流程。
标签:xml,beanFactory,Spring,BeanFactory,ele,delegate,解析,BeanDefinition From: https://www.cnblogs.com/xfeiyun/p/17888325.html