抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

SpringIOC-自定义标签解析

自定义标签解析流程

parseCustomElement

接着上文parseCustomElement是自定义标签解析的入口

使用了Spring的SPI发现思想,从标签元素获取URI,接着从spring.handlers获取对应的解析类进行操作 具体流程可以参考《命名空间解析》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 解析自定义标签的主类
*
*/
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
// 1.拿到节点ele的命名空间,例如常见的:
// <context> 节点对应命名空间: http://www.springframework.org/schema/context
// <aop> 节点对应命名空间: http://www.springframework.org/schema/aop
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
// 2.拿到命名空间对应的的handler, 例如:http://www.springframework.org/schema/context 对应 ContextNameSpaceHandler
// 2.1 getNamespaceHandlerResolver: 拿到namespaceHandlerResolver
// 2.2 resolve: 使用namespaceHandlerResolver解析namespaceUri, 拿到namespaceUri对应的NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 3.使用拿到的handler解析节点(ParserContext用于存放解析需要的一些上下文信息)
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

我们构建 XmlReaderContext 时会创建一个默认的DefaultNamespaceHandlerResolver,这边拿到的就是当时创建的 DefaultNamespaceHandlerResolver 对象,例如下图。

在进行resolve获取NamespaceHandler的时候会调用NamespaceHandler.init方法进行解析类的初始化注册

我们就拿context标签来举例,其他的都一样根据spring.handlers的配置,会调用到ContextNamespaceHandler的init方法

我们接下来就以最重要也是最常用的component-scan包扫描来讲解下具体流程,

1
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());

我们发现核心解析类是ComponentScanBeanDefinitionParser

DefaultNamespaceHandlerResolver.resolve

根据URI获取对那个的NamespaceHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* Locate the {@link NamespaceHandler} for the supplied namespace URI
* from the configured mappings.
* 根据URI获取对那个的NamespaceHandler
*
* @param namespaceUri the relevant namespace URI
* @return the located {@link NamespaceHandler}, or {@code null} if none found
*/
@Override
@Nullable
public NamespaceHandler resolve(String namespaceUri) {
// 1.拿到配置文件的所有命名空间和对应的handler
// 例如:"http://www.springframework.org/schema/aop" -> "org.springframework.aop.config.AopNamespaceHandler"
//获取spring中所有jar包里面的 "META-INF/spring.handlers"文件,并且建立映射关系
Map<String, Object> handlerMappings = getHandlerMappings();
// 2.拿到当前命名空间对应的handler (可能是handler的className,也可能是已经实例化的handler)
//根据namespaceUri:http://www.springframework.org/schema/p,获取到这个命名空间的处理类
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
// 2.1 如果不存在namespaceUri对应的handler,则返回null
return null;
} else if (handlerOrClassName instanceof NamespaceHandler) {
// 2.2 如果是已经实例化的handler,则直接强转返回
return (NamespaceHandler) handlerOrClassName;
} else {
// 2.3 如果是handler的className
String className = (String) handlerOrClassName;
try {
// 2.3.1 根据className,使用类加载器拿到该类
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
// 2.3.2 校验是否是继承自NamespaceHandler(所有的handler都继承自NamespaceHandler)
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
// 2.3.3 使用无参构造函数实例化handlerClass类
//实例化NamespaceHandler解析类
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
// 2.3.4 调用handler类的初始化方法(将命名空间下的节点名和对应的解析器注册到parsers缓存中)
//调用处理类的init方法,在init方法中完成标签元素解析类的注册
namespaceHandler.init();
// 2.3.5 将实例化的handler放到缓存,替换原来的className
// 原来为: namespaceUri -> handler的className,会被覆盖成: namespaceUri -> 实例化的handler
handlerMappings.put(namespaceUri, namespaceHandler);
// 返回实例化后的handler对象
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);
}
}
}

getHandlerMappings

获取所有的 URI和NamespaceHandler的映射关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* Load the specified NamespaceHandler mappings lazily.
* 获取所有的 URI和NamespaceHandler的映射关系
*/
private Map<String, Object> getHandlerMappings() {
// 1.如果handlerMappings已经加载过,则直接返回
Map<String, Object> handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
synchronized (this) {
// 2.如果handlerMappings还没加载过,则进行加载
handlerMappings = this.handlerMappings;
if (handlerMappings == null) {
if (logger.isTraceEnabled()) {
logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
}
try {
// 2.1 使用给定的类加载器从指定的类路径资源加载所有属性
//加载"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());
// 2.2 将Properties转换成Map, mappings -> handlerMappings
//将属性文件合并到handlerMappings的MAP中
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
// 2.3 将加载到的所有命名空间映射放到缓存
this.handlerMappings = handlerMappings;
} catch (IOException ex) {
throw new IllegalStateException(
"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
}
}
}
}
return handlerMappings;
}

我们知道 handlerMappingsLocation 的默认值为 “META-INF/spring.handlers”,因此在这边会使用指定的 classLoader 从所有类路径资源(META-INF/spring.handlers)加载所有属性,并使用 Properties 来存放 spring.handlers 文件中的内容(命名空间和 handler 的键值对,例如下图)。

2.2 将 Properties 转成 Map。其中 key 为命名空间,例如:http://www.springframework.org/schema/context;value 为命名空间对应的 handler,例如:org.springframework.context.config.ContextNamespaceHandler,所有的handler都需要自己实现。

2.3 最后将转换后的 handlerMappings 放到缓存。

namespaceHandler#init

点击该方法,我们可以看到有很多个实现类,分别对应了不同的命名空间 Handler。

我们拿最常见的命名空间:http://www.springframework.org/schema/context 来举例,对应的 handler 为 ContextNamespaceHandler。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ContextNamespaceHandler extends NamespaceHandlerSupport {

@Override
public void init() {
//注册property-placeholder 解析器
//<context:property-placeholder location="classpath*:jdbc.properties"/>
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());

//注册property-override注册器
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());

//注册annotation-config解析器
//<contex:annotation-config/>
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());

//注册component-scan解析器
//<context:component-scan base-package="com.xiangxue.jack"/>
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());
}

}

内容很简单,就是给 context 命名空间下的不同节点指定了不同的 BeanDefinition 解析器,并将节点名和对应的解析器注册到缓存中,见代码块4详解。例如,最常用的 component-scan 对应 ComponentScanBeanDefinitionParser 。

registerBeanDefinitionParser

1
2
3
4
5
6
7
8
9
10
private final Map<String, BeanDefinitionParser> parsers =
new HashMap<String, BeanDefinitionParser>();
//...

/**
* 注册标签的解析类
*/
protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {
this.parsers.put(elementName, parser);
}

将节点名和对应的解析器放到 parsers 缓存中。

2.使用拿到的 BeanDefinition 解析器解析 element 节点。例如:使用 ComponentScanBeanDefinitionParser 解析器解析 component-scan 节点。

到此为此,自定义命名空间的解析操作基本完成,只剩下具体解析器解析对应节点的内容没有写。

自定义命名空间节点常见的有:<context:component-scan />、<context:annotation-config />、aop:aspectj-autoproxy/、<tx:annotation-driven /> 等

parse

调用ContextNamespaceHandler的parse方法进行解析

首先会找到对应的component-scan元素的解析类ComponentScanBeanDefinitionParser进行元素解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 将元素转换成BeanDefinition
*/
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 1.findParserForElement: 给element寻找对应的BeanDefinition解析器
// 2.使用BeanDefinition解析器解析element节点
//获取对应元素的BeanDefinitionParser 例如component-scan
BeanDefinitionParser parser = findParserForElement(element, parserContext);
//调用BeanDefinitionParser的parse将元素解析为BeanDefinition
return (parser != null ? parser.parse(element, parserContext) : null);
}

@Nullable
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
// 1.1 拿到节点的localName,例如:annotation-config、component-scan
String localName = parserContext.getDelegate().getLocalName(element);
// 1.2 从parsers缓存中,拿到localName对应的解析器, 例如: component-scan -> ComponentScanBeanDefinitionParser
BeanDefinitionParser parser = this.parsers.get(localName);
if (parser == null) {
parserContext.getReaderContext().fatal(
"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
}
return parser;
}

1.从 parsers 缓存中(见代码块4),查找 element 节点对应的 BeanDefinition 解析器。parsers缓存如下:

ComponentScanBeanDefinitionParser.parse

调用ComponentScanBeanDefinitionParser的parse完成component-scan标签的解析

<context:component-scan base-package=”com.test”/>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 主要完成创建解析器以及扫描的主流程处理
*/
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 1.拿到<context:component-scan>节点的base-package属性值
//获取basePackage属性
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
// 2.解析占位符, 例如 ${basePackage}
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
// 3.解析base-package(允许通过 ",; \t\n" 中的任一符号填写多个),例如: com.text.open.one;com.test.open.two
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);

//配置注解扫描器
// Actually scan for bean definitions and register them.
// 4.构建和配置ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);

//扫描并把扫描的类封装成beanDefinition对象 核心方法,重要程度 5
// 5.使用scanner在指定的basePackages包中执行扫描,返回已注册的bean定义
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
//注册需要进行处理的组件如 @Configuration,@Autowired等注解的处理类
// 6.组件注册(包括注册一些内部的注解后置处理器、触发注册事件)
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

return null;
}

configureScanner

创建以及配置扫描器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* 创建以及配置扫描器
*
* @param parserContext
* @param element
* @return
*/
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
// 1.解析use-default-filters属性,默认为true,用于指示是否使用默认的filter
boolean useDefaultFilters = true;
//@Service @Component 默认filter
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.parseBoolean(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
}

//创建注解的扫描器
// Delegate bean definition registration to scanner class.
// 2.构建ClassPathBeanDefinitionScanner,将bean定义注册委托给scanner类
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
// 3.解析resource-pattern属性
if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
}

try {
// 4.解析name-generator属性
parseBeanNameGenerator(element, scanner);
} catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}

try {
// 5.解析scope-resolver、scoped-proxy属性
parseScope(element, scanner);
} catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
// 6.解析类型过滤器
//对 include-filter 以及exclude-filter 配置的支持
parseTypeFilters(element, scanner, parserContext);

return scanner;
}
createScanner

创建扫描器

这里面注意一下 将上面的

boolean useDefaultFilters = true;

使用默认扫描器传过去了

1
2
3
4
5
6
7
8
9
10
11
/**
* 创建默认扫描器
*/
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
//创建默认扫描器 mybatis用到了这个扫描器用来扫描@Mapper注解
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
readerContext.getEnvironment(), readerContext.getResourceLoader());
}



ClassPathBeanDefinitionScanner

创建扫描器是创建一个ClassPathBeanDefinitionScanner的实例,首先看一下构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {

Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
//使用默认的过滤器
if (useDefaultFilters) {
//将默认扫描的注解注册到扫描器中
//@Service @Component
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
registerDefaultFilters

这个方法很关键,向全局的includeFilters注册了@Component注解,代表着扫描器需要扫描@Component的注解

但是@Service,@Repository,@Controller 都继承了@Component注解所以,这些注解都会被扫描到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
// 1.添加@Component注解Filter到includeFilters中
//过滤器中添加需要扫描的注解类型
//注册Component注解 其他@Service,@Repository@Controller 都继承了@Component注解
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
//获取扫描器的ClassLoader
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
// 2.添加@ManagedBean注解Filter到includeFilters中
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 {
// 3.添加@Named注解Filter到includeFilters中,这边会抛ClassNotFoundException
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.
}
}

​ 这边会尝试添加3个 AnnotationTypeFilter 到 includeFilters 中,但是默认情况下,添加 @Named 注解对应的 AnnotationTypeFilter 时会抛异常。因此,执行完该方法,includeFilters 会有两个 AnnotationTypeFilter,分别对应 @Component 注解和 @ManagedBean 注解,如下图所示。

parseTypeFilters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
* 对 include-filter 以及exclude-filter 配置的支持
*
* @param element
* @param scanner
* @param 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();
// 1.遍历解析element下的所有子节点
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
// 拿到节点的localName
// 例如节点:<context:exclude-filter type="" expression=""/>,localName为:exclude-filter
String localName = parserContext.getDelegate().getLocalName(node);
try {
//对include-filter的支持
/**
* 例如
* <context:component-scan base-package="com.joonwhee.open">
* <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
* </context:component-scan>
*/
// 2.解析include-filter子节点
if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
// 2.1 构建TypeFilter
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
// 2.2 添加到scanner的includeFilters属性
scanner.addIncludeFilter(typeFilter);
//对exclude-filter的支持
// 3.解析exclude-filter子节点
} else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
// 3.1 构建TypeFilter
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
// 3.2 添加到scanner的excludeFilters属性
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());
}
}
}
}

@SuppressWarnings("unchecked")
protected TypeFilter createTypeFilter(Element element, @Nullable ClassLoader classLoader,
ParserContext parserContext) throws ClassNotFoundException {

// 1.获取type、expression
String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression);
// 2.根据filterType,返回对应的TypeFilter,例如annotation返回AnnotationTypeFilter
if ("annotation".equals(filterType)) {
// 2.1 指定过滤的注解, expression为注解的类全名称, 例如: org.springframework.stereotype.Controller
return new AnnotationTypeFilter((Class<Annotation>) ClassUtils.forName(expression, classLoader));
} else if ("assignable".equals(filterType)) {
// 2.2 指定过滤的类或接口, 包括子类和子接口, expression为类全名称
return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader));
} else if ("aspectj".equals(filterType)) {
// 2.3 指定aspectj表达式来过滤类, expression为aspectj表达式字符串
return new AspectJTypeFilter(expression, classLoader);
} else if ("regex".equals(filterType)) {
// 2.4 通过正则表达式来过滤类, expression为正则表达式字符串
return new RegexPatternTypeFilter(Pattern.compile(expression));
} else if ("custom".equals(filterType)) {
// 2.5 用户自定义过滤器类型, expression为自定义过滤器的类全名称
Class<?> filterClass = ClassUtils.forName(expression, classLoader);
// 自定义的过滤器必须实现TypeFilter接口, 否则抛异常
if (!TypeFilter.class.isAssignableFrom(filterClass)) {
throw new IllegalArgumentException(
"Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression);
}
return (TypeFilter) BeanUtils.instantiateClass(filterClass);
} else {
throw new IllegalArgumentException("Unsupported filter type: " + filterType);
}
}

​ 我们知道,当我们配置了 component-scan 时,Spring会去扫描 base-package 下所有使用了 @Component(包括@Controller、@Repository、@Service) 注解的 bean。这是因为 use-default-filters 属性默认值为 true,而通过代码块registerDefaultFilters我们知道,use-default-filters = true 时,includeFilters 会有两个 AnnotationTypeFilter,分别对应 @Component 注解和 @ManagedBean 注解。

如果我们想排除掉使用了 @Controller 注解的 bean 时,就可以使用 exclude-filter 属性,例如以下配置。

1
2
3
<context:component-scan base-package="com.test.spring.demo">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
小结

主要完成对扫描器的创建和配置

主要流程如下

  1. 创建ClassPathBeanDefinitionScanner扫描器,并且使用使用默认的过滤器
  2. 默认过滤器将@Component注解注册到includeFilters

doScan

扫描的核心方法,完成将扫描到的class转换为BeanDefinition

主要步骤如下扫描class生成BeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* 扫描的核心方法
*
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//1. 对基本扫描包进行循环
for (String basePackage : basePackages) {
// 2.扫描basePackage,将符合要求的bean定义全部找出来(这边符合要求最常见的就是使用Component注解)
//扫描到有注解的类并封装成BeanDefinition对象
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
//3. 遍历扫描出来的所有的BeanDefinition
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
// 4.解析@Scope注解, 包括scopeName(默认为singleton,常见的还有prototype), 和proxyMode(默认不使用代理, 可选接口代理/类代理)
candidate.setScope(scopeMetadata.getScopeName());
// 5.使用beanName生成器来生成beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//如果candidate 实现了AbstractBeanDefinition
if (candidate instanceof AbstractBeanDefinition) {
// 6.进一步处理BeanDefinition对象,比如: 此bean是否可以自动装配到其他bean中
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
//如果实现了AnnotatedBeanDefinition
if (candidate instanceof AnnotatedBeanDefinition) {
// 7.处理定义在目标类上的通用注解,包括@Lazy, @Primary, @DependsOn, @Role, @Description
//支持了@Lazy @DependOn注解
//将公共注解设置进BeanDefinition 中
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 8.检查beanName是否已经注册过,如果注册过,检查是否兼容
if (checkCandidate(beanName, candidate)) {
// 9.将当前遍历bean的 bean定义和beanName封装成BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 10.根据proxyMode的值(步骤4中解析), 选择是否创建作用域代理
//这里不看
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 11.注册BeanDefinition(注册到beanDefinitionMap、beanDefinitionNames、aliasMap缓存)
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}

findCandidateComponents

根据classpath 扫描路径 并将类转换为BeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 根据classpath 扫描路径 并将类转换为BeanDefinition
*
*/
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
//快速从索引库中找到符合的BeanDefinition元素
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
} else {
//扫描符合条件的class并生成BeanDefinition
return scanCandidateComponents(basePackage);
}
}
scanCandidateComponents

扫描符合条件的class并生成BeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* 扫描符合条件的class并生成BeanDefinition
*
* @param basePackage
* @return
*/
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// 1.根据我们配置的包名,组装成要扫描的通配包路径,例如:com.spring.test 会被组装成: classpath*:com/spring/test/**/*.class
//生成包的扫描路径
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;

// 2.根据通配包路径匹配拿到所有匹配的类资源(本项目依赖的jar,如果路径也符合,则会一起扫描进来)
//这里递归寻找文件 扫描basepackage找到符合的class
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
//设置日志打印
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
//循环扫描资源
// 3.遍历所有匹配的类资源
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
// 4.使用metadataReader读取资源,MetadataReader是专门用来访问元数据的类(包括: 类元数据ClassMetadata、注解元数据AnnotationMetadata等)
//包装了类的基本信息的对象
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 5.使用过滤器检查给定的类是否为候选类(候选类: 与excludeFilters的所有Filter不匹配,并且与includeFilters的至少一个Filter匹配)
//如果类上面有includeFilters注解
if (isCandidateComponent(metadataReader)) {
//创建扫描BeanDefinition 主要完成对注解元数据的设置
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
// 6.判断sbd是否为候选类(独立的 && (具体的实现类 || (抽象类 && 类中有方法使用@Lookup注解)))
//校验bean不是接口 不是抽象类,没有Lookup注解
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
// 7.确定是候选类,则添加到candidates
//将创建的BeanDefinition放进集合
candidates.add(sbd);
} else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
} else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
}
}
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
} else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
getMetadataReader

来到SimpleMetadataReaderFactory类

主要作用是创建SimpleMetadataReader类,并对Resources进行注解的搜集

1
2
3
4
5
6
7
8
9
10
/**
* 创建SimpleMetadataReader
* @param resource
* @return
* @throws IOException
*/
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
SimpleMetadataReader

该类是创建一个元数据读取对象,主要的任务就是收集注解信息

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 创建基本的元数据读取器
* @param resource
* @param classLoader
* @throws IOException
*/
SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader);
//根据注解搜集类的基本信息
getClassReader(resource).accept(visitor, PARSING_OPTIONS);
this.resource = resource;
this.annotationMetadata = visitor.getMetadata();
}
isCandidateComponent

该方法是对includeFilters以及excludeFilters的处理

我们在上面registerDefaultFilters方法中将@Component注解注册到了includeFilters中所以

根据传过来的元数据信息如果有@Service,@Repository,@Controller,@Component任意一个注解就会返回true,接着就会被封装到BeanDefinition中返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 对excludeFilters 以及includeFilters是处理
* 如果includeFilters能匹配上就返回true
* 如果excludeFilters能匹配上就返回false
*
* @param metadataReader the ASM ClassReader for the class
* @return whether the class qualifies as a candidate component
*/
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
//遍历所有的excludeFilters
for (TypeFilter tf : this.excludeFilters) {
// 如果metadataReader与excludeFilters中的任意一个匹配,则返回false,表示metadataReader对应的类不是候选者类
//进行匹配如果能匹配上返回false
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}

//遍历所有的includeFilters
// includeFilters默认包含: org.springframework.stereotype.Component注解、javax.annotation.ManagedBean注解
for (TypeFilter tf : this.includeFilters) {
//进行匹配如果能匹配上则进行具体规则的匹配,一般是能匹配上的
// 如果metadataReader与includeFilters中的任意一个TypeFilter匹配(如果tf为Component注解:metadataReader对应的类使用了Component则匹配),
// 则判断@Conditional注解是否匹配(@Conditional基本不用,此处不深入解析);如果匹配,则返回true,表示metadataReader对应的类为候选者类
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}

​ 这边的 excludeFilters 和 includeFilters 在上面的代码块3、代码块4中已经介绍过。默认情况下 excludeFilters 为空,includeFilters 包含:@Component 注解的 TypeFilter、@ManagedBean 注解的 TypeFilter。

​ 因此,在正常情况下,使用了 @Component(包括被 @Component 修饰的 @Controller、@Repository、@Service) 注解的类在这边会返回 true,表示该类是候选者类。

isCandidateComponent

校验bean不是接口 不是抽象类,没有Lookup注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Determine whether the given bean definition qualifies as candidate.
* <p>The default implementation checks whether the class is not an interface
* and not dependent on an enclosing class.
* <p>Can be overridden in subclasses.
* 校验bean不是接口 不是抽象类,没有Lookup注解
*
* @param beanDefinition the bean definition to check
* @return whether the bean definition qualifies as a candidate component
*/
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
AnnotationMetadata metadata = beanDefinition.getMetadata();
// isIndependent:确定底层类是否是独立的,即它是否是顶级类或嵌套类(静态内部类),它可以独立于封闭类构造。
// isConcrete:返回底层类是表示具体类,即:既不是接口也不是抽象类。
// isAbstract:返回底层类是否标记为抽象。
// hasAnnotatedMethods:确定基础类是否具有使用给定注解(@Lookup)类型进行注解(或元注解)的任何方法。
return (metadata.isIndependent() && (metadata.isConcrete() ||
(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}

正常使用,在前两个条件校验完就会返回 true,不会走到后面两个条件。

小结

findCandidateComponents方法主要完成了根据路径找到对应的class并封装成BeanDefinition

步骤如下

  1. 生成包的扫描路径
  2. 递归的方式找到basepackage下的所有的class文件,并包装成Resource
  3. 收集Resource文件的注解,并将Resource的注解包装为MetadataReader
  4. 通过includeFilters和excludeFilters对MetadataReader进行过滤,因为默认includeFilters有@Component的注解所有会将@Service,@Repository,@Controller,@Component等注解的类筛选出来
  5. 筛选出来的类创建BeanDefinition
  6. 校验bean不是接口 不是抽象类,没有Lookup注解
  7. 添加到BeanDefinition的集合中返回

resolveScopeMetadata

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
annDef.getMetadata(), this.scopeAnnotationType);
// 如果使用了@Scope注解
if (attributes != null) {
// 解析scopeName属性
metadata.setScopeName(attributes.getString("value"));
// 解析proxyMode属性
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = this.defaultProxyMode;
}
metadata.setScopedProxyMode(proxyMode);
}
}
return metadata;
}

​ 如果使用了@Scope注解,则解析注解的属性。这边的 defaultProxyMode 取决于代码块1中步骤5的 scope-resolver、scoped-proxy 属性,默认为 ScopedProxyMode.NO。可以通过 scoped-proxy 来设置,例如下面配置 defaultProxyMode 的值就为 ScopedProxyMode.TARGET_CLASS。

1
2
3
<context:component-scan base-package="com.test.spring.demo" scoped-proxy="targetClass">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

postProcessBeanDefinition

进一步处理BeanDefinition对象

1
2
3
4
5
6
7
8
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
// 给beanDefinition设置默认值
beanDefinition.applyDefaults(this.beanDefinitionDefaults);
if (this.autowireCandidatePatterns != null) {
// 设置此bean是否可以自动装配到其他bean中, 默认为true
beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
}
}

processCommonDefinitionAnnotations

该方法是对公共注解的解析,将公共注解设置进BeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* 将公共注解设置进BeanDefinition 中
*
* @param abd BeanDefinition
*/
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
//将公共注解设置进BeanDefinition 中
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}

/**
* 将公共注解设置进BeanDefinition中
*
* @param abd BeanDefinition
* @param metadata 注解元数据
*/
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
//获取懒加载的注解
// 解析@Lazy注解, 设置是否延迟加载
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
//对懒加载的支持
if (lazy != null) {
//将Lazy值设置进BeanDefinition
abd.setLazyInit(lazy.getBoolean("value"));
} else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
//将Lazy值设置进BeanDefinition
abd.setLazyInit(lazy.getBoolean("value"));
}
}
//对Primary注解的支持
// 解析@Primary注解, 自动装配时当出现多个Bean都匹配时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
// (场景较小, 如果可能出现多个匹配者时, 可以使用@Autowired @Qualifier的组合)
if (metadata.isAnnotated(Primary.class.getName())) {
//将Primary值设置进BeanDefinition
abd.setPrimary(true);
}
//对DependsOn注解的支持
// 解析@DependOn注解
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
//将DependsOn值设置进BeanDefinition
abd.setDependsOn(dependsOn.getStringArray("value"));
}
//对Role注解的支持
// 解析@Role注解
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
//将Role值设置进BeanDefinition
abd.setRole(role.getNumber("value").intValue());
}
//对Description注解的支持
// 解析@Description注解
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
//将Description值设置进BeanDefinition
abd.setDescription(description.getString("value"));
}
}

checkCandidate

对beanDefinition 进行检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* Check the given candidate's bean name, determining whether the corresponding
* bean definition needs to be registered or conflicts with an existing definition.
* <p>
* 对beanDefinition 进行检查
*/
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
// 1.如果该注册表(beanDefinitionMap缓存)没有包含beanName, 则返回true,代表可以注册该bean定义
if (!this.registry.containsBeanDefinition(beanName)) {
return true;
}
//检查beanName 是否已经存在
// 2.如果注册表中包含beanName
// 2.1拿到注册表中该beanName的BeanDefinition
BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
// 2.2拿到原始BeanDefinition(使用了代理的BeanDefinition会有原始BeanDefinition)
BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
if (originatingDef != null) {
// 2.3如果有原始BeanDefinition, 则使用原始BeanDefinition
existingDef = originatingDef;
}
// 3.检查新BeanDefinition是否与原BeanDefinition兼容,如果兼容则返回false,跳过注册
if (isCompatible(beanDefinition, existingDef)) {
return false;
}
// 4.如果不兼容,则抛异常
throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +
"' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +
"non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");
}

applyScopedProxyMode

根据proxyMode的值,选择是否创建作用域代理

1
2
3
4
5
6
7
8
9
10
11
12
13
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
// 1.如果不需要创建代理,则直接返回bean定义
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
// 2.判断是使用基于类的代理还是基于接口的代码, 基于类: 使用CGLIB代理, 基于接口: 使用JDK动态代理
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
// 3.使用相应的代理模式, 创建一个scope代理
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
createScopedProxy

创建动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public static BeanDefinitionHolder createScopedProxy(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {

return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}

public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
BeanDefinitionRegistry registry, boolean proxyTargetClass) {

// 拿到原始bean的beanName
String originalBeanName = definition.getBeanName();
// 拿到原始bean的BeanDefinition
BeanDefinition targetDefinition = definition.getBeanDefinition();
// 为原始bean生成了一个新的beanName(加了个前缀: scopedTarget.)
String targetBeanName = getTargetBeanName(originalBeanName);

// Create a scoped proxy definition for the original bean name,
// "hiding" the target bean in an internal target definition.
// 使用ScopedProxyFactoryBean作为beanClass创建代理BeanDefinition
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
// 将原始bean封装成BeanDefinitionHolder,设置到代理的decoratedDefinition属性
proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
// 设置代理的原始BeanDefinition属性值
proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
proxyDefinition.setSource(definition.getSource());
proxyDefinition.setRole(targetDefinition.getRole());

proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
if (proxyTargetClass) {
// 根据类做代理, proxyTargetClass属性默认为true,因此我们不需要在此处设置它
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
} else {
// 根据接口做代理, 设置proxyTargetClass属性值为false
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
}

// Copy autowire settings from original bean definition.
// 从原始bean定义复制autowire设置
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
proxyDefinition.setPrimary(targetDefinition.isPrimary());
if (targetDefinition instanceof AbstractBeanDefinition) {
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
}

// The target bean should be ignored in favor of the scoped proxy.
// 隐藏原始的bean
targetDefinition.setAutowireCandidate(false);
targetDefinition.setPrimary(false);

// Register the target bean as separate bean in the factory.
// 注册原始bean的BeanDefinition
registry.registerBeanDefinition(targetBeanName, targetDefinition);

// Return the scoped proxy definition as primary bean definition
// (potentially an inner bean).
// 将代理bean封装成BeanDefinitionHolder对象并返回
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}

registerBeanDefinition

该方法是最后一步,完成完善后的BeanDefinition的注册

1
2
3
4
5
6
7
/**
* 注册BeanDefinition
*/
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
//注册BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
小结

因为返回的BeanDefinition是一个扫描的BeanDefinition,只有一个MetadataReader的封装,需要将MetadataReader的数解析到BeanDefinition的各个属性中

具体流程如下

  1. 将MetadataReader转换为ScopeMetadata获取Scope属性完成Scope的设置
  2. 生成beanName
  3. 完成公共属性的设置
  4. 对BeanDefinition做一些检查然后封装为definitionHolder
  5. 完成BeanDefinition的注册

registerComponents

注册需要进行处理的组件如 @Configuration,@Autowired等注解的处理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
protected void registerComponents(
XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {

Object source = readerContext.extractSource(element);
// 1.使用注解的tagName(例如: context:component-scan)和source 构建CompositeComponentDefinition
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);

// 2.将扫描到的所有BeanDefinition添加到compositeDef的nestedComponents属性中
for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
}

// Register annotation config processors, if necessary.
boolean annotationConfig = true;
if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
// 3.获取component-scan标签的annotation-config属性值(默认为true)
annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
}
if (annotationConfig) {
// 4.如果annotation-config属性值为true,在给定的注册表中注册所有用于注解的Bean后置处理器
//这里稍微看一下,注册了几个比较重要的BeanPostProcessor类
//AutowiredAnnotationBeanPostProcessor,ConfigurationClassPostProcessor,CommonAnnotationBeanPostProcessor
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
// 5.将注册的注解后置处理器的BeanDefinition添加到compositeDef的nestedComponents属性中
compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
}
}
// 6.触发组件注册事件,默认实现为EmptyReaderEventListener(空实现,没有具体操作)
readerContext.fireComponentRegistered(compositeDef);
}

registerAnnotationConfigProcessors

如果annotation-config属性值为true,在给定的注册表中注册所有用于注解的Bean后置处理器

这里稍微看一下,注册了几个比较重要的BeanPostProcessor类

  • AutowiredAnnotationBeanPostProcessor
  • ConfigurationClassPostProcessor
  • CommonAnnotationBeanPostProcessor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
* Register all relevant annotation post processors in the given registry.
* 注册配置类的解析器
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {

DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// 1.设置dependencyComparator属性
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// 2.设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象)
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}

Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

// 3.注册内部管理的用于处理@Configuration注解的后置处理器的bean
//注册@Configuration 解析类
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//将ConfigurationClassPostProcessor转换为BeanDefinition
//该类非常重要,解决了@Configuration,@Component,@ComponentScan,@Import,@ImportResource,@Bean注解的扫描以及注册BeanDefinition
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 3.1 registerPostProcessor: 注册BeanDefinition到注册表中
//注册BeanDefinition并返回创建的BeanDefinitionHolder
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// 4.注册内部管理的用于处理@Autowired、@Value、@Inject以及@Lookup注解的后置处理器的bean
//注册@Autowired 解析类
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//将AutowiredAnnotationBeanPostProcessor转换为BeanDefinition
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
//注册BeanDefinition并返回创建的BeanDefinitionHolder
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}


/**
* 注册公共注解的解析类
* Common注解包括
* @Resource
* @PostConstruct
* @PreDestroy
*/

// 6.注册内部管理的用于处理JSR-250注解(例如@Resource, @PostConstruct, @PreDestroy)的后置处理器的bean
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// 7.注册内部管理的用于处理JPA注解的后置处理器的bean
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
} catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}

// 8.注册内部管理的用于处理@EventListener注解的后置处理器的bean
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}

// 9.注册内部管理用于生产ApplicationListener对象的EventListenerFactory对象
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}

return beanDefs;
}
registerPostProcessor

注册PostProcessor

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 注册PostProcessor
*
*/
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
// 1.设置role
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//2. 注册BeanDefinition
registry.registerBeanDefinition(beanName, definition);
//3.封装成BeanDefinitionHolder并返回
return new BeanDefinitionHolder(definition, beanName);
}

至此,context:component-scan 节点解析已经完成,主要做的事情有:

​ 扫描 base-package 目录,将使用了 @Component、@Controller、@Repository、@Service 注解的 bean 注册到注册表中(其实就是beanDefinitionMap、beanDefinitionNames、aliasMap缓存中),跟之前解析默认命名空间一样,也是在后续创建 bean 时需要使用这些缓存。
添加了几个内部的注解相关的后置处理器:

  • ConfigurationClassPostProcessor
  • AutowiredAnnotationBeanPostProcessor
  • RequiredAnnotationBeanPostProcessor

总结

同时,本文的结束,也标志着 obtainFreshBeanFactory 方法的详解正式结束。

简单来说,有以下几个主要操作:

  • 根据 spring.xml 中 contextConfigLocation 配置的路径,读取 Spring 配置文件,并封装成 Resource。
  • 根据 Resource 加载 XML 配置文件,并解析成 Document 对象 。
  • 拿到 Document 中的根节点,遍历根节点和所有子节点。
  • 根据命名空间,进行不同的解析,将 bean 节点内容解析成 BeanDefinition。
  • 将 BeanDefinition 注册到注册表中(也就是beanDefinitionMap、beanDefinitionNames、aliasMap缓存)。

执行完 obtainFreshBeanFactory 方法,我们得到了三个重要的对象:

  • 新的 BeanFactory。

  • beanDefinitionNames 缓存。

  • beanDefinitionMap 缓存。

这三个对象在之后的 IoC 构建过程中会发挥重要的作用。

评论