参考资料:
《Spring IoC源码学习:context:component-scan 节点详解》
前文:
《Spring IOC:parseCustomElement调用链》
写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。
目录
5、processCommonDefinitionAnnotations
2、registerAnnotationConfigProcessors
一、parse
在前文中,我们了解到当 element 为 <context:component-scan /> 节点时,findParserForElement(element, parserContext) 会返回 ComponentScanBeanDefinitionParser,接着执行 ComponentScanBeanDefinitionParser类的parse 方法。
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 1.findParserForElement: 给element寻找对应的BeanDefinition解析器
// 2.使用BeanDefinition解析器解析element节点
return findParserForElement(element, parserContext).parse(element, parserContext);
}
在parse方法中,我们首先解析base-package属性,拿到要扫描的路径,进行解析,如果有使用了占位符的还需要进行替换,如果有使用了分隔符","或者";"的,还需要拆分成数组。然后调用configureScanner方法构建ClassPathBeanDefinitionScanner来为后续扫描做准备。拿到ClassPathBeanDefinitionScanner后,调用其doScan方法,将扫描路径下使用了相关注解的类加入到beanDefinition中。最后,再注册其余的组件,如后置处理器等。
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 拿到<context:component-scan>节点的base-package属性值
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
// 解析占位符, 例如 ${basePackage}
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
// 解析base-package(允许通过 ",; \t\n" 中的任一符号填写多个)
// String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
// 构建和配置ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
// 使用scanner在指定的basePackages包中执行扫描,返回已注册的bean定义
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
// 组件注册(包括注册一些内部的注解后置处理器、触发注册事件)
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
二、configureScanner
1、configureScanner
进入configureScanner方法,会先读取该节点下是否配置了use-default-filters属性,该属性用来指定是否使用默认的过滤器(注意是过滤器,不是过滤规则)。然后调用createScanner方法创建扫描器,创建完毕后,再解析一些其他属性,如resource-pattern、name-generator等。最后调用parseTypeFilters方法解析类型过滤器。
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
// 解析use-default-filters属性,默认为true,用于指示是否使用默认的filter
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,将bean定义注册委托给scanner类
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
// 解析resource-pattern属性
if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
}
try {
// 解析name-generator属性
parseBeanNameGenerator(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
try {
// 解析scope-resolver、scoped-proxy属性
parseScope(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
// 解析类型过滤器
parseTypeFilters(element, scanner, parserContext);
return scanner;
}
2、createScanner
createScanner方法判断是否使用默认的filter,如果是,则继续调用registerDefaultFilters方法
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
readerContext.getEnvironment(), readerContext.getResourceLoader());
}
// ClassPathBeanDefinitionScanner.java
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
// 注册默认的filter
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
3、registerDefaultFilters
registerDefaultFilters方法会将@Component和@ManagedBean对应的filter加入到includeFilters中。
// ClassPathScanningCandidateComponentProvider.java
protected void registerDefaultFilters() {
// 添加@Component注解Filter到includeFilters中
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
// 添加@ManagedBean注解Filter到includeFilters中
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.debug("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 {
// 添加@Named注解Filter到includeFilters中
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
4、parseTypeFilters
解析当前节点下的子节点,读取可能存在的include-filter和exclude-filter节点,然后针对读取到的属性调用createTypeFilter方法创建typeFilter,并加入到扫描器中。
protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {
// Parse exclude and include filter elements.
ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();
NodeList nodeList = element.getChildNodes();
// 遍历解析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 {
/**
* 例如
* <context:component-scan base-package="com.joonwhee.open">
* <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
* </context:component-scan>
*/
// 解析include-filter子节点
if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
// 构建TypeFilter
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
// 添加到scanner的includeFilters属性
scanner.addIncludeFilter(typeFilter);
}
// 解析exclude-filter子节点
else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
// 构建TypeFilter
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
// 添加到scanner的excludeFilters属性
scanner.addExcludeFilter(typeFilter);
}
} catch (Exception ex) {
parserContext.getReaderContext().error(
ex.getMessage(), parserContext.extractSource(element), ex.getCause());
}
}
}
}
5、createTypeFilter
读取include-filter和exclude-filter节点中的type、expression属性,根据不同的属性创建AnnotationTypeFilter。比如type="annotation"时,表明按注解过滤,expression中设置注解的路径,如expression="org.springframework.stereotype.Controller",则会过滤掉@Controller注解。
protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader, ParserContext parserContext) {
// 获取type、expression
String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression);
try {
// 根据filterType,返回对应的TypeFilter,例如annotation返回AnnotationTypeFilter
if ("annotation".equals(filterType)) {
// 指定过滤的注解, expression为注解的类全名称, 例如: org.springframework.stereotype.Controller
return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression));
}
else if ("assignable".equals(filterType)) {
// 指定过滤的类或接口, 包括子类和子接口, expression为类全名称
return new AssignableTypeFilter(classLoader.loadClass(expression));
}
else if ("aspectj".equals(filterType)) {
// 指定aspectj表达式来过滤类, expression为aspectj表达式字符串
return new AspectJTypeFilter(expression, classLoader);
}
else if ("regex".equals(filterType)) {
// 通过正则表达式来过滤类, expression为正则表达式字符串
return new RegexPatternTypeFilter(Pattern.compile(expression));
}
else if ("custom".equals(filterType)) {
// 用户自定义过滤器类型, expression为自定义过滤器的类全名称
Class<?> filterClass = classLoader.loadClass(expression);
// 自定义的过滤器必须实现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);
}
}
catch (ClassNotFoundException ex) {
throw new FatalBeanException("Type filter class not found: " + expression, ex);
}
}
三、doScan
1、doScan
doScan方法会调用findCandidateComponents将符合要求的bean都找出来(即使用了注解,且满足filter过滤规则的bean)。遍历所有符合要求的bean,解析@Scope,生成beanName,然后调用postProcessBeanDefinition、processCommonDefinitionAnnotations进一步解析候选bean。后续再封装BeanDefinitionHolder,然后根据proxyMode的值选择是否创建作用域代理,最后注册BeanDefinition(即beanDefinitionMap、beanDefinitionNames、aliasMap这三个缓存)
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
// 遍历basePackages
for (String basePackage : basePackages) {
// 扫描basePackage,将符合要求的bean定义全部找出来(这边符合要求最常见的就是使用Component注解)
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 遍历所有候选的bean定义
for (BeanDefinition candidate : candidates) {
// 解析@Scope注解, 包括scopeName(默认为singleton,常见的还有prototype), 和proxyMode(默认不使用代理, 可选接口代理/类代理)
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 使用beanName生成器来生成beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
// 进一步处理BeanDefinition对象,比如: 此bean是否可以自动装配到其他bean中
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
// 处理定义在目标类上的通用注解,包括@Lazy, @Primary, @DependsOn, @Role, @Description
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 检查beanName是否已经注册过,如果注册过,检查是否兼容
if (checkCandidate(beanName, candidate)) {
// 将当前遍历bean的 bean定义和beanName封装成BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 根据proxyMode的值(步骤4中解析), 选择是否创建作用域代理
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册BeanDefinition(注册到beanDefinitionMap、beanDefinitionNames、aliasMap缓存)
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
2、 findCandidateComponents
读取配置的路径,将所有的类都加载进来,并使用过滤器检查给定的类是否为候选类,如满足要求,则加入到candidates中
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
try {
// 根据我们配置的包名,组装成要扫描的通配包路径,例如:com.joonwhee.open 会被组装成: classpath*:com/joonwhee/open/**/*.class
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 根据通配包路径匹配拿到所有匹配的类资源(本项目依赖的jar,如果路径也符合,则会一起扫描进来)
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
// 遍历所有匹配的类资源
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
// 使用metadataReader读取资源,MetadataReader是专门用来访问元数据的类(包括: 类元数据ClassMetadata、注解元数据AnnotationMetadata等)
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
// 使用过滤器检查给定的类是否为候选类(候选类: 与excludeFilters的所有Filter不匹配,并且与includeFilters的至少一个Filter匹配)
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
// 判断sbd是否为候选类(独立的 && (具体的实现类 || (抽象类 && 类中有方法使用@Lookup注解)))
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
// 确定是候选类,则添加到candidates
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;
}
2.1、isCandidateComponent
判断metadataReader(MetadataReader是专门用来访问元数据的类)是否与excludeFilters 和 includeFilters中的TypeFilter相匹配。
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
// 如果metadataReader与excludeFilters中的任意一个匹配,则返回false,表示metadataReader对应的类不是候选者类
return false;
}
}
// includeFilters默认包含: org.springframework.stereotype.Component注解、javax.annotation.ManagedBean注解
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
// 如果metadataReader与includeFilters中的任意一个TypeFilter匹配(如果tf为Component注解:metadataReader对应的类使用了Component则匹配),
// 则判断@Conditional注解是否匹配(@Conditional基本不用,此处不深入解析);如果匹配,则返回true,表示metadataReader对应的类为候选者类
return isConditionMatch(metadataReader);
}
}
return false;
}
2.2、isCandidateComponent
继续判断该类是否满足要求。
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()))));
}
3、resolveScopeMetadata
解析@Scope注解,判断是否使用代理模式。defaultProxyMode取决前文中parseScope方法读取到的scope-resolver、scoped-proxy属性,可以通过 scoped-proxy 来设置,默认为 ScopedProxyMode.NO。
@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 == null || proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = this.defaultProxyMode;
}
metadata.setScopedProxyMode(proxyMode);
}
}
return metadata;
}
4、postProcessBeanDefinition
这一步给beanDefinition设置默认值,同时读取autowire-candidate,该属性用来设置某个bean是否在自动注入的时候是否为作为候选bean。
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));
}
}
<bean id="beantest" class="com.test" autowire-candidate="false"/>
5、processCommonDefinitionAnnotations
继续解析常用属性,包括@Lazy, @Primary, @DependsOn, @Role, @Description。
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
// 解析@Lazy注解, 设置是否延迟加载
if (metadata.isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
}
else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
}
// 解析@Primary注解, 自动装配时当出现多个Bean都匹配时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
// (场景较小, 如果可能出现多个匹配者时, 可以使用@Autowired @Qualifier的组合)
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
// 解析@DependOn注解
if (metadata.isAnnotated(DependsOn.class.getName())) {
abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
}
if (abd instanceof AbstractBeanDefinition) {
// 解析@Role注解
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
if (metadata.isAnnotated(Role.class.getName())) {
absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
}
// 解析@Description注解
if (metadata.isAnnotated(Description.class.getName())) {
absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
}
}
}
6、checkCandidate
利用beanDefinitionMap判断该beanName是否已在缓存中,如不在,直接返回,如在,则取出该beanName在beanDefinitionMap中的BeanDefinition,继续判断,如使用了代理,则取出代理的BeanDefinition,并作为缓存中的值与当前要注册的BeanDefinition比较,判断是否兼容。
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
// 如果该注册表(beanDefinitionMap缓存)没有包含beanName, 则返回true,代表可以注册该bean定义
if (!this.registry.containsBeanDefinition(beanName)) {
return true;
}
// 如果注册表中包含beanName
// 拿到注册表中该beanName的BeanDefinition
BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
// 拿到原始BeanDefinition(使用了代理的BeanDefinition会有原始BeanDefinition)
BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
if (originatingDef != null) {
// 如果有原始BeanDefinition, 则使用原始BeanDefinition
existingDef = originatingDef;
}
// 检查新BeanDefinition是否与原BeanDefinition兼容,如果兼容则返回false,跳过注册
if (isCompatible(beanDefinition, existingDef)) {
return false;
}
// 如果不兼容,则抛异常
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() + "]");
}
7、applyScopedProxyMode
判断是否使用代理模式,如是,则继续判断是基于接口还是基于类的代理,前者使用CGlib代理,后者使用JDK动态代理,确认代理模式后,创建相应的scope代理。
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
// 如果不需要创建代理,则直接返回bean定义
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
// 判断是使用基于类的代理还是基于接口的代码, 基于类: 使用CGLIB代理, 基于接口: 使用JDK动态代理
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
// 使用相应的代理模式, 创建一个scope代理
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
8、registerBeanDefinition
调用 BeanDefinitionReaderUtils 工具类来完成 BeanDefinition 的注册。此方法在默认命名空间节点解析中已介绍过(《Spring IOC:parseDefaultElement调用链》第5小节),这里不再赘述,主要作用在于注册beanDefinitionMap、beanDefinitionNames、aliasMap这三个缓存。
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
// 调用BeanDefinitionReaderUtils工具类来完成BeanDefinition的注册
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
三、registerComponents
1、registerComponents
判断是否需要注册基于注解的bean后置处理器,默认为treu,然后调用registerAnnotationConfigProcessors方法进行注册。
protected void registerComponents(
XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
Object source = readerContext.extractSource(element);
// 使用注解的tagName(例如: context:component-scan)和source 构建CompositeComponentDefinition
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
// 将扫描到的所有BeanDefinition添加到compositeDef的nestedComponents属性中
for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
}
boolean annotationConfig = true;
if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
// 获取component-scan标签的annotation-config属性值(默认为true)
annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
}
if (annotationConfig) {
// 如果annotation-config属性值为true,在给定的注册表中注册所有用于注解的Bean后置处理器
Set<BeanDefinitionHolder> processorDefinitions =
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
// 将注册的注解后置处理器的BeanDefinition添加到compositeDef的nestedComponents属性中
compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
}
}
// 触发组件注册事件,默认实现为EmptyReaderEventListener(空实现,没有具体操作)
readerContext.fireComponentRegistered(compositeDef);
}
2、registerAnnotationConfigProcessors
判断是否包含常用注解的BeanDefinition,包括@Configuration、@Autowired、@Required、@Resource等基于后置处理器实现的注解,然后调用registerPostProcessor注册。
核心注册方法registerBeanDefinition 在《Spring IOC:parseDefaultElement调用链》中第5小节已分析过,这里省略。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// 设置dependencyComparator属性
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// 设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象)
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
// 注册内部管理的用于处理@Configuration注解的后置处理器的bean
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// registerPostProcessor: 注册BeanDefinition到注册表中
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册内部管理的用于处理@Autowired、@Value、@Inject以及@Lookup注解的后置处理器的bean
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册内部管理的用于处理@Required注解的后置处理器的bean
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册内部管理的用于处理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));
}
// 注册内部管理的用于处理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));
}
// 注册内部管理的用于处理@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));
}
// 注册内部管理用于生产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;
}
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
// 设置role
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册BeanDefinition
registry.registerBeanDefinition(beanName, definition);
// 封装成BeanDefinitionHolder并返回
return new BeanDefinitionHolder(definition, beanName);
}
总结:
<context:component-scan> 节点解析过程主要分为以下几步:
1、扫描 base-package 目录,将所有基于@Component注解的bean取出,并加入到注册表中(依然是这三个重要缓存中,beanDefinitionMap、beanDefinitionNames、aliasMap,和前文parseDefaultElement调用链解析默认命名空间一样)
2、将几个常规的bean后置处理器加入到BeanDefinition中,比如@Autowired所基于的AutowiredAnnotationBeanPostProcessor等。