Spring5源码4-XML配置文件解析
欢迎大家关注 github.com/hsfxuebao ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈
1. spring项目搭建
1.1 导入jar依赖
spring中最核心的4个jar:
- spring-beans
- spring-core
- spring-context
- spring-expression
一个最最简单的spring工程,理论上就只需要一个jar就够了
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
1.2 XSD引入
spring中要引入自定义标签,必须要引入其对应的XSD文件
,XSD 是编写 xml 文件的一种规范
,有了这个规范才能校验 xml 是否写错;
例如要引入自定义标签<context:component-scan base-package="org.example"/>
,就必须引入这个标签对应的 XSD 文件。
在标签对应的jar包下面找到对应的spring.schemas
,在这个文件中就会有对应的XSD路径和命名空间。
1.3 spring 容器加载方式
1. 类路径获取配置文件
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("beans.xml");
2、文件系统路径获取配置文件【绝对路径】
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("E:\\idea\\public\\springdemo\\src\\main\\resources\\spring.xml");
3、无配置文件加载容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext("MainText.class");
4、springboot加载容器
ApplicationContext applicationContext = new EmbeddedWebApplicationContext();
2. xml配置文件案例
AbstractApplicationContext.refresh()方法,是spring容器启动过程中的核心方法,spring容器要加载必须执行该方法。
2.1 测试类
@Component
public class Person {
private String name;
// @Autowired 依赖的组件是多实例的时候不能使用@Autowired
private Cat cat;
@Lookup // 去容器中找,@Bean的这种方式注册的Person @Lookup不生效
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
'}';
}
容器加载
public class XmlMainText {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
Person bean = context.getBean(Person.class);
System.out.println(bean);
}
}
spring.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
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.hsf.spring"></context:component-scan>
<bean class="com.hsf.spring.beans.Person" id="person">
<property name= "name" value="zhangsan"></property>
</bean>
</beans>
打印结果
zhangsan
3. xml配置文件解析源码
ClassPathXmlApplicationContext构造器:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
进入this
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
// 创建解析器,设置configLocations
setConfigLocations(configLocations);
if (refresh) {
// 刷新容器
refresh();
}
}
- setConfigLocations(configLocations);----创建解析器,设置configLocations
3.1 核心方法AbstractApplicationContext#refresh()
// 容器刷新的十二大步骤
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 容器启动的状态
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
// 1.准备上下文环境
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/** 1、创建BeanFactory对象
* 2、xml解析
* 传统标签解析:bean、import等
* 自定义标签解析 如:<context:component-scan base-package="org.example"/>
* 自定义标签解析流程:
* a、根据当前解析标签的头信息找到对应的namespaceUri
* b、加载spring所以jar中的spring.handlers文件。并建立映射关系
* c、根据namespaceUri从映射关系中找到对应的实现了NamespaceHandler接口的类
* d、调用类的init方法,init方法是注册了各种自定义标签的解析类
* e、根据namespaceUri找到对应的解析类,然后调用paser方法完成标签解析
* 3、把解析出来的xml标签封装成BeanDefinition对象
*/
// 2. 工厂创建:BeanFactory 第一次开始创建的时候,有xml解析逻辑
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 3. 预准备工厂,给容器中注册了环境信息作为单实例Bean 方便后续自动装配
// 并且放了一些后置处理器(监听、xxxAware功能)
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 留给子类的模板方法,允许子类继续对工厂执行一些处理
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
// 5. 【大核心】工厂增强:执行所有的BeanFactory 后置增强器 利用BeanFactory后置增强器对工厂进行修改或增强
// 配置类也会在这个解析
// BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor 完成对这两个接口的调用
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 6. 【核心】注册 所有的Bean的后置处理器
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
// 7. 初始化国际化组件
initMessageSource();
// Initialize event multicaster for this context.
// 8. 初始化事件派发 功能
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 9. 留给子类继续增强处理逻辑
// 这个方法着重理解模板设计模式,因为在springboot中,这个方法是用来做内嵌tomcat启动的
onRefresh();
// Check for listener beans and register them.
// 10. 注册事件监听器,从容器中获取所有的ApplicationListener
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 11. 【大核心】bean创建:完成BeanFactory 初始化(工厂里面所有的组件都好了)
/*
* 这个方法一定要理解要具体看
* 1、bean实例化过程
* 2、ioc
* 3、注解支持
* 4、BeanPostProcessor的执行
* 5、Aop的入口
*/
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 12. 发布事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
本文 重点分析obtainFreshBeanFactory()
方法中关于 xml配置文件解析相关,其他步骤以后再说。
3.2 obtainFreshBeanFactory()
该方法主要进行xml解析工作,流程如下:
- 创建XmlBeanDefinitionReader对象
- 通过Reader对象加载配置文件
- 根据加载的配置文件把配置文件封装成document对象
- 创建BeanDefinitionDocumentReader对象,DocumentReader负责对document对象解析
- parseDefaultElement(ele, delegate);负责常规标签解析
- delegate.parseCustomElement(ele);负责自定义标签解析
- 最终解析的标签封装成BeanDefinition并缓存到容器中
进入obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新BeanFactory,注解模式下就是准备工厂,xml模式下会解析xml
refreshBeanFactory();
return getBeanFactory();
}
进入refreshBeanFactory();
这里spring使用了模板设计模式,通过子类实现钩子方法来干预父类的业务执行流程。
3.3 AbstractRefreshableApplicationContext#refreshBeanFactory()
protected final void refreshBeanFactory() throws BeansException {
//如果BeanFactory不为空,则清除BeanFactory和里面的实例
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 1.创建DefaultListableBeanFactory
//BeanFactory 实例工厂
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 2.设置是否可以循环依赖 allowCircularReferences
//是否允许使用相同名称重新注册不同的bean实现.
customizeBeanFactory(beanFactory);
// 3.解析xml,并把xml中的标签封装成BeanDefinition对象
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
3.3.1 AbstractXmlApplicationContext#loadBeanDefinitions(beanFactory);
创建XmlBeanDefinitionReader对象
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// 准备一个BeanDefinitionReader 读取器, 这里是一个委托模式
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
//这里传一个this进去,因为ApplicationContext是实现了ResourceLoader接口的
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);
// todo 加载所有BeanDefinition
loadBeanDefinitions(beanDefinitionReader);
}
3.3.2 AbstractXmlApplicationContext#loadBeanDefinitions(beanDefinitionReader);
- 后面会多次调用好几个类中的loadBeanDefinitions这个方法
- 通过Reader对象加载配置文件
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
// 获取所有的配置文件的位置信息,可以一次传入很多配置文件
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// todo 读取文件
reader.loadBeanDefinitions(configLocations);
}
}
3.3.3 AbstractBeanDefinitionReader#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;
}
3.3.4 AbstractBeanDefinitionReader#loadBeanDefinitions(location);
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
3.3.5 AbstractBeanDefinitionReader#loadBeanDefinitions(location, null);
用流的方式加载配置文件,然后封装成Resource对象
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// 把字符串类型的xml文件路径,形如:classpath*:user/**/*-context.xml,转换成Resource对象类型
// 其实就是用流的方式加载配置文件,然后封装成Resource对象,不重要,可以不看
// 得到实体文件对应的资源
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// todo 加载
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
}
3.3.6 AbstractBeanDefinitionReader#loadBeanDefinitions(resources);
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
// todo
count += loadBeanDefinitions(resource);
}
return count;
}
loadBeanDefinitions(resource)是模板设计模式,钩子方法
3.3.7 XmlBeanDefinitionReader#loadBeanDefinitions(new EncodedResource(resource))
EncodedResource带编码的对Resource对象的封装
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// EncodedResource 带编码的对Resource对象的封装
return loadBeanDefinitions(new EncodedResource(resource));
}
3.3.8 XmlBeanDefinitionReader#doLoadBeanDefinitions(inputSource, encodedResource.getResource())
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);
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
// 获取Resource对象中的xml文件流对象
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
//InputSource是jdk中的sax xml文件解析对象
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// todo
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
3.3.9 XmlBeanDefinitionReader#doLoadDocument(inputSource, resource)
根据加载的配置文件把配置文件封装成document对象
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 把inputSource 封装成Document文件对象,这是jdk的API
// dom解析工具 把xml变成Document
Document doc = doLoadDocument(inputSource, resource);
// todo 主要看这个方法,根据解析出来的document对象,拿到里面的标签元素封装成BeanDefinition
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
...
}
3.3.10 XmlBeanDefinitionReader#registerBeanDefinitions(doc, resource)
这个document对象就是配置文件bean.xml
里的内容
创建BeanDefinitionDocumentReader对象,DocumentReader负责对document对象解析
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//委托模式,BeanDefinitionDocumentReader委托这个类进行document的解析
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
//主要看这个方法,createReaderContext(resource) XmlReaderContext上下文,封装了XmlBeanDefinitionReader对象
// todo BeanDefinitionDocumentReader 把Document解析
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
3.3.11 DefaultBeanDefinitionDocumentReader#registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
把root节点传进去
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
3.3.12 DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions(Element root)
3.3.13 DefaultBeanDefinitionDocumentReader#parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
- parseDefaultElement(ele, delegate);负责默认标签解析
- delegate.parseCustomElement(ele);负责自定义标签解析
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;
// 遍历文档中的所有标签
//判断是否是默认的Namespace,http://www.springframework.org/schema/beans
if (delegate.isDefaultNamespace(ele)) {
// bean标签,走默认标签解析
parseDefaultElement(ele, delegate);
}
else {
// 自定义标签解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
默认标签解析( < bean >)
- 解析document对象并包装成BeanDefinition对象
解析bean标签内的属性
(id,class,scope,primary),并设置到BeanDefinition对象中再解析bean下面的子标签
(lookup-method,replaced-method,property,constructor-arg等)- 把BeanDefinition
封装成BeanDefinitionHolder对象
- 对BeanDefinitionHolder对象进行缓存和注册
3.3.13.1 DefaultBeanDefinitionDocumentReader#parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//import标签解析 重要程度 1
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//alias标签解析 别名标签 重要程度 1
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//bean标签,重要程度 5
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
3.3.13.2 DefaultBeanDefinitionDocumentReader#processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// todo 把当前标签解析完了,BeanDefinition 和beanName都封装了Holder中
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 装饰者设计模式,加上SPI设计思想,解析namespaceuri方法
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// todo 完成document到BeanDefinition对象转换后,对BeanDefinition对象进行缓存注册
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));
}
}
3.3.13.3 BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element ele)
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取bean标签内的id
String id = ele.getAttribute(ID_ATTRIBUTE);
//获取bean标签内的name
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//获取bean标签内的别名
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//将id赋给beanName
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");
}
}
//检查beanName是否重复
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// todo 解析bean,返回beanDefinition对象
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);
// 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);
// 将beanDefinition封装成BeanDefinitionHolder返回
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
3.3.13.4 BeanDefinitionParserDelegate#parseBeanDefinitionElement(ele, beanName, containingBean)
解析bean标签,包装成beanDefinition对象返回
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//创建GenericBeanDefinition对象
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 以下是解析Bean标签里面的数据,填充完BeanDefinition
// 解析bean标签的属性,并把解析出来的属性设置到BeanDefinition对象中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析bean中的meta标签
parseMetaElements(ele, bd);
//解析bean中的lookup-method标签 重要程度:2
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析bean中的replaced-method标签 重要程度:2
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析bean中的constructor-arg标签 重要程度:2
parseConstructorArgElements(ele, bd);
//解析bean中的property标签 重要程度:2
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
//包装成beanDefinition对象返回
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;
}
3.3.13.5 回到3.3.13.3步,将beanDefinition封装成BeanDefinitionHolder返回
BeanDefinitionHolder 构造器:
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, @Nullable String[] aliases) {
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
Assert.notNull(beanName, "Bean name must not be null");
this.beanDefinition = beanDefinition;
this.beanName = beanName;
this.aliases = aliases;
}
3.3.13.6 回到3.3.13.2步,BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder)
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
return decorateBeanDefinitionIfRequired(ele, originalDef, null);
}
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = originalDef;
//根据bean标签属性装饰BeanDefinitionHolder,比如<bean class="xx" p:username="fisher"/>
// Decorate based on custom attributes first.
NamedNodeMap attributes = ele.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
// Decorate based on custom nested elements.
// 根据bean标签子元素装饰BeanDefinitionHolder
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
// todo
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
3.3.13.7 BeanDefinitionParserDelegate#decorateIfRequired(Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd)
public BeanDefinitionHolder decorateIfRequired(
Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
// 根据node获取到node的命名空间,形如:http://www.springframework.org/schema/p
String namespaceUri = getNamespaceURI(node);
if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
// todo 这里有SPI服务发现的思想,根据配置文件获取namespaceUri对应的处理类
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler != null) {
//调用NamespaceHandler处理类的decorate方法,开始具体装饰过程,并返回装饰完的对象
//org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
BeanDefinitionHolder decorated =
handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
if (decorated != null) {
return decorated;
}
}
else if (namespaceUri.startsWith("http://www.springframework.org/schema/")) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
}
else {
// A custom namespace, not to be handled by Spring - maybe "xml:...".
if (logger.isDebugEnabled()) {
logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
}
}
}
return originalDef;
}
3.3.13.8 DefaultNamespaceHandlerResolver#resolve(String namespaceUri)
@Override
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
// todo 获取spring中所有jar包里面的 "META-INF/spring.handlers"文件,并且建立uri和处理类的映射关系
Map<String, Object> handlerMappings = getHandlerMappings();
//根据namespaceUri:http://www.springframework.org/schema/p,获取到这个命名空间的处理类
// todo 通过uri在映射关系内找到处理类
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
// todo 通过类名反射出处理类
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
//调用处理类的init方法,在init方法中完成标签元素解析类的注册
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
"] for namespace [" + namespaceUri + "]", ex);
}
catch (LinkageError err) {
throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
className + "] for namespace [" + namespaceUri + "]", err);
}
}
}
3.3.13.9 DefaultNamespaceHandlerResolver#getHandlerMappings()
private Map<String, Object> getHandlerMappings() {
Map<String, Object> handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
synchronized (this) {
handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
if (logger.isTraceEnabled()) {
logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
}
try {
// 用InputStream流的方式,加载"META-INF/spring.handlers"文件,包装成Properties 对象
// handlerMappingsLocation 为常量META-INF/spring.handlers
Properties mappings =
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isTraceEnabled()) {
logger.trace("Loaded NamespaceHandler mappings: " + mappings);
}
//所有"META-INF/spring.handlers"文件里面的内容建立映射关系
handlerMappings = new ConcurrentHashMap<>(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
}
catch (IOException ex) {
throw new IllegalStateException(
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
}
}
}
}
return handlerMappings;
}
- DefaultNamespaceHandlerResolver类中定义了一个常量,文件路径
META-INF/spring.handlers
public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
- 构造方法,点击this
public DefaultNamespaceHandlerResolver() {
this(null, DEFAULT_HANDLER_MAPPINGS_LOCATION);
}
- 赋值操作
public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader, String handlerMappingsLocation) {
Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null");
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
this.handlerMappingsLocation = handlerMappingsLocation;
}
3.3.13.10 回到3.3.13.8步,DefaultNamespaceHandlerResolver#resolve(String namespaceUri)
点开处理类,可以发现所有的处理类都会实现NamespaceHandler接口
public class SimplePropertyNamespaceHandler implements NamespaceHandler {
通过反射实例化处理类,并强转为NamespaceHandler
调用init()方法
3.3.13.11 回到3.3.13.2 步
DefaultBeanDefinitionDocumentReader#registerBeanDefinition(bdHolder, getReaderContext().getRegistry())
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// todo 把当前标签解析完了,BeanDefinition 和beanName都封装了Holder中
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 装饰者设计模式,加上SPI设计思想,解析namespaceuri方法
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// todo 完成document到BeanDefinition对象转换后,对BeanDefinition对象进行缓存注册
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));
}
}
完成document到BeanDefinition对象转换后,对BeanDefinition对象进行缓存注册:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// todo 完成BeanDefinition的注册,重点看,重要程度 5
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
// 建立别名和 id的映射,这样就可以根据别名获取到id
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
3.3.13.12 DefaultListableBeanFactory#registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
完成BeanDefinition的注册
@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);
}
}
// todo 先判断BeanDefinition是否已经注册
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
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 + "]");
}
}
// 把beanDefinition缓存到map中
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);
//把beanName放到beanDefinitionNames list中,这个list着重记住,bean实例化的时候需要用到
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
- beanDefinitionMap:beanDefinitionNames存了所有beanDefiniton的名称
3.3.14 DefaultBeanDefinitionDocumentReader#delegate.parseCustomElement(ele)
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;
// 遍历文档中的所有标签
//判断是否是默认的Namespace,http://www.springframework.org/schema/beans
if (delegate.isDefaultNamespace(ele)) {
// bean标签,走默认标签解析
parseDefaultElement(ele, delegate);
}
else {
// 自定义标签解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
自定义标签解析( < context>)
3.3.14.1 BeanDefinitionParserDelegate#parseCustomElement(Element ele)
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// todo
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
使用xml的方式加载spring的配置文件,启动spring容器。
3.3.14.2 BeanDefinitionParserDelegate#parse(Element element, ParserContext parserContext)
public BeanDefinition parse(Element element, ParserContext parserContext) {
// todo
BeanDefinitionParser parser = findParserForElement(element, parserContext);
// parse 方法
return (parser != null ? parser.parse(element, parserContext) : null);
}
3.3.14.3 BeanDefinitionParserDelegate#findParserForElement(Element element, ParserContext parserContext)
- this.parsers.get(localName)为什么能够拿到BeanDefinitionParser对象
- 通过spring.handlers文件找到namespaceuri(www.springframework.org/schema/cont…
init方法建立了映射关系
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}
将ComponentScanBeanDefinitionParser放入map中,对应的key是component-scan:
protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
this.parsers.put(elementName, parser);
}
parsers是父类的Map,父类NamespaceHandlerSupport实现NamespaceHandler接口,所以handler才能实现多态:
3.3.14.4 返回parser对象,回到3.3.14.2步,进入ComponentScanBeanDefinitionParser#parse(Element element, ParserContext parserContext)
parser()主要工作:
- 1、扫描路径.class后缀的文件
- 2、要判断类上是否有注解,并封装成metadata对象
- 3、genericBeanDefinition.setBeanClass(BeanClass.class)
- 4、完成BeanDefinition的注册(beandefinitionNames,beandefinitionMap)
创建注解扫描器
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
//获取basePackage属性
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
//可以用逗号分开
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// todo 创建注解扫描器
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
// todo 扫描并把扫描的类封装成beanDefinition对象 核心方法,重要程度 5
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
// 如果加了@Component的类中,又加了@Autowired、@Value、@Resource、@PostConstruct、@PreDestroy注解,使用这个方法就可以扫描得到
// 在Bean的实例化过程中有至关重要的作用
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
3.3.14.5 ComponentScanBeanDefinitionParser#configureScanner(parserContext, element)
//使用默认的过滤器
boolean useDefaultFilters = true;
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
}
//创建注解的扫描器
// Delegate bean definition registration to scanner class.
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
3.3.14.6 ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner()构造方法
使用默认的过滤器
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
// todo
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
3.3.14.7 ClassPathScanningCandidateComponentProvider#registerDefaultFilters();
protected void registerDefaultFilters() {
// Component注解
//过滤器中添加需要扫描的注解类型,把@Component注解添加进来
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
Service也添加了@Component注解,所以@Service也能被扫描到
AnnotationTypeFilter用来包装需要扫描的注解的类型
3.3.14.8 回到3.3.14.5步,ComponentScanBeanDefinitionParser#parseTypeFilters(element, scanner, parserContext);
protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {
// Parse exclude and include filter elements.
ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();
NodeList nodeList = element.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
String localName = parserContext.getDelegate().getLocalName(node);
try {
// todo include-filter
if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
scanner.addIncludeFilter(typeFilter);
}
// todo exclude-filter
else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
scanner.addExcludeFilter(typeFilter);
}
}
catch (ClassNotFoundException ex) {
parserContext.getReaderContext().warning(
"Ignoring non-present type filter class: " + ex, parserContext.extractSource(element));
}
catch (Exception ex) {
parserContext.getReaderContext().error(
ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
}
}
}
将需要被扫描到的注解和不要被扫描到的注解的类型,分别放到2个集合中
private final List<TypeFilter> includeFilters = new ArrayList<>();
private final List<TypeFilter> excludeFilters = new ArrayList<>();
3.3.14.9 回到3.3.14.4步, ClassPathBeanDefinitionScanner#doScan(String… basePackages)
public BeanDefinition parse(Element element, ParserContext parserContext) {
...
// todo 创建注解扫描器
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
// todo 扫描并把扫描的类封装成beanDefinition对象 核心方法,重要程度 5
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
// 如果加了@Component的类中,又加了@Autowired、@Value、@Resource、@PostConstruct、@PreDestroy注解,使用这个方法就可以扫描得到
// 在Bean的实例化过程中有至关重要的作用
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 找到候选组件,需要扫描需要扫描的组件
// todo 扫描到有注解的类并封装成BeanDefinition对象
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
//支持了@Lazy @DependOn注解
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// todo BeanDefinition注册
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
3.3.14.10 ClassPathScanningCandidateComponentProvider#findCandidateComponents(String basePackage)
componentsIndex一般情况下都为null,所以会走else
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
// todo 扫描所有组件
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
// todo
return scanCandidateComponents(basePackage);
}
}
3.3.14.11 ClassPathScanningCandidateComponentProvider#scanCandidateComponents(String basePackage)
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
//这里递归寻找文件,所有的.class文件
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
try {
//扫描类里的信息放在MetadataReader对象中
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//判断类上面是否有includeFilters集合内包含的注解
if (isCandidateComponent(metadataReader)) {
//根据MetadataReader 对象内的类的基本信息,包装成BeanDefinition对象
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
...
}
...
}
}
...
return candidates;
}
AnnotationMetadata对象内有类的所有信息,方法、属性、注解等
3.3.14.12 回到3.3.14.9步,ClassPathScanningCandidateComponentProvider#registerBeanDefinition(definitionHolder, this.registry)
BeanDefinition注册:
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
和默认标签解析的注册方法,3.3.13.12步一模一样, DefaultListableBeanFactory#registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// todo 完成BeanDefinition的注册,重点看,重要程度 5
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
// 建立别名和 id的映射,这样就可以根据别名获取到id
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
3.3.14.13 回到3.3.14.9步,ComponentScanBeanDefinitionParser#registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
- 如果加了@Component的类中,又加了@Autowired、@Value、@Resource、@PostConstruct、@PreDestroy注解,使用这个方法就可以扫描得到
- 在Bean的实例化过程中有至关重要的作用
4. 总结
obtainFreshBeanFactory()方法:
- 创建XmlBeanDefinitionReader对象
- Reader通过xml文件路径加载配置文件,转换成Resource对象类型
- 把Resource对象封装成document对象
- 创建BeanDefinitionDocumentReader对象,负责对document对象解析
- 根据namespace判断走默认标签解析还是自定义标签解析
- parseDefaultElement(ele, delegate);负责常规标签解析
- 6.1、解析document对象并包装成BeanDefinition对象
- 6.2、再将BeanDefinition封装成BeanDefinitionHolder返回
- 6.3、对BeanDefinitionHolder对象进行装饰,解析属性标签或者构造方法标签
- 6.4、通过SPI加载所有"META-INF/spring.handlers"文件,建立映射关系,找到namespaceUri对应的实现了NamespaceHandler接口的处理类,通过反射实例化处理类,并强转为NamespaceHandler,调用处理类的init方法,完成标签元素解析类的注册;调用NamespaceHandler类的decorate装饰
- 6.5、registerBeanDefinition对BeanDefinition进行注册,加入到beanDefinitionMap和beanDefinitionNames
- delegate.parseCustomElement(ele);负责自定义标签解析
- 7.1. 通过SPI找到自定义标签的处理类,调用init方法,完成标签元素解析类的注册,建立标签和解析类的映射关系
- 7.2. 调用ComponentScanBeanDefinitionParser的parse方法,
- 7.3. 创建注解扫描器,使用默认的过滤器,把需要被扫描到的注解和不要被扫描到的注解的类型添加进来
- 7.4. 递归扫描路径下所有.class后缀的文件,把类的信息放在MetadataReader对象中,判断类上面是否包含我需要的注解,封装成BeanDefinition对象
- 7.5. 完成BeanDefinition的注册
参考文章
Spring5源码注释github地址 Spring源码深度解析(第2版) spring源码解析 Spring源码深度解析笔记 Spring注解与源码分析 Spring注解驱动开发B站教程
转载自:https://juejin.cn/post/7132658819678601247