接上一篇xml解析,回到
org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext)
.parse(element, parserContext);
}
ComponentScanBeanDefinitionParser 标签解析器
component-scan标签解析类
<!-- 激活Spring注解方式:自动扫描,并注入bean -->
<context:component-scan base-package="com.consult.action"
use-default-filters=""
annotation-config="">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Service" />
</context:component-scan>
- Annotation org.example.SomeAnnotation符合SomeAnnoation的target class
- Assignable org.example.SomeClass指定class或interface的全名
- Aspectj org.example…*Service+AspectJ語法
- Regex org.example.Default.* Regelar Expression
- Custom org.example.MyTypeFilterSpring3新增自定义Type,见
org.springframework.core.type.TypeFilter
在解析类里面完成了
1.基本包的扫描
2.类型过滤器的配置
3.<context:annotation-config/>
配置的兼容
4.注解处理器BeanPostProcessor的注册
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse
// base-package 标签属性值,即扫描的包配置
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
ClassPathBeanDefinitionScanner scanner =
configureScanner(parserContext, element);
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#configureScanner
//默认过滤器标记
boolean useDefaultFilters = true;
ClassPathBeanDefinitionScanner scanner =
createScanner(parserContext.getReaderContext(), useDefaultFilters);
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#createScanner
return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(),
useDefaultFilters,
readerContext.getEnvironment(),
readerContext.getResourceLoader());
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner(org.springframework.beans.factory.support.BeanDefinitionRegistry, boolean, org.springframework.core.env.Environment, org.springframework.core.io.ResourceLoader)
//注册默认的过滤器
if (useDefaultFilters) {
registerDefaultFilters();
}
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#registerDefaultFilters
// 扫描 @Component 注解以及 @Component注解的子类,如@Service
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
// 扫描 @ManagedBean 注解 JSR-250
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>)
ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
// 扫描 @Named 注解 JSR-330
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
见 AnnotationTypeFilter 类中的 annotationType 字段,注解类型
返回到
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#configureScanner
parseTypeFilters(element, scanner, parserContext);
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parseTypeFilters
//include-filter 元素解析
if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
scanner.addIncludeFilter(typeFilter);
}
//exclude-filter 元素解析
else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
scanner.addExcludeFilter(typeFilter);
}
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#createTypeFilter
// annotation 过滤是最常用的
if ("annotation".equals(filterType)) {
return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression));
}
else if ("assignable".equals(filterType)) {
return new AssignableTypeFilter(classLoader.loadClass(expression));
}
else if ("aspectj".equals(filterType)) {
return new AspectJTypeFilter(expression, classLoader);
}
else if ("regex".equals(filterType)) {
return new RegexPatternTypeFilter(Pattern.compile(expression));
}
else if ("custom".equals(filterType)) {
Class<?> filterClass = classLoader.loadClass(expression);
if (!TypeFilter.class.isAssignableFrom(filterClass)) {
throw new IllegalArgumentException(
"Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression);
}
return (TypeFilter) BeanUtils.instantiateClass(filterClass);
}
返回到
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents
// 将配置包路径的 点 转为 斜杠
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 加载包下的 class 文件
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
org.springframework.context.support.AbstractApplicationContext#getResources
return this.resourcePatternResolver.getResources(locationPattern);
org.springframework.core.io.support.PathMatchingResourcePatternResolver#getResources
// 如果是 classpath*: 前缀时
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
// a class path resource (multiple resources for same name possible)
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
// a class path resource pattern
// 查看该方法
return findPathMatchingResources(locationPattern);
}
else {
// all class path resources with the given name
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
org.springframework.core.io.support.PathMatchingResourcePatternResolver#findPathMatchingResources
if (rootDirURL.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirURL, subPattern, getPathMatcher()));
}
// 识别 jar 包
else if (ResourceUtils.isJarURL(rootDirURL) || isJarResource(rootDirResource)) {
result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirURL, subPattern));
}
else {
// class 文件添加到结集中,查看 doFindPathMatchingFileResources result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
}
org.springframework.core.io.support.PathMatchingResourcePatternResolver#doFindPathMatchingFileResources
rootDir = rootDirResource.getFile().getAbsoluteFile();
return doFindMatchingFileSystemResources(rootDir, subPattern);
org.springframework.core.io.support.PathMatchingResourcePatternResolver#doFindMatchingFileSystemResources
Set<File> matchingFiles = retrieveMatchingFiles(rootDir, subPattern);
org.springframework.core.io.support.PathMatchingResourcePatternResolver#retrieveMatchingFiles
String fullPattern = StringUtils.replace(rootDir.getAbsolutePath(), File.separator, "/");
doRetrieveMatchingFiles(fullPattern, rootDir, result);
org.springframework.core.io.support.PathMatchingResourcePatternResolver#doRetrieveMatchingFiles
File[] dirContents = dir.listFiles();
for (File content : dirContents) {
String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, "/");
if (content.isDirectory() && getPathMatcher().matchStart(fullPattern, currPath + "/")) {
if (!content.canRead()) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping subdirectory [" + dir.getAbsolutePath() +
"] because the application is not allowed to read the directory");
}
}
else {
// 作递归查找文件
doRetrieveMatchingFiles(fullPattern, content, result);
}
}
if (getPathMatcher().match(fullPattern, currPath)) {
// 是文件是加入到集合中
result.add(content);
}
}
返回到
org.springframework.core.io.support.PathMatchingResourcePatternResolver#doFindMatchingFileSystemResources
// matchingFiles 所有class 文件
Set<File> matchingFiles = retrieveMatchingFiles(rootDir, subPattern);
Set<Resource> result = new LinkedHashSet<Resource>(matchingFiles.size());
for (File file : matchingFiles) {
// class 文件转为 Resource后,添加到集合中
result.add(new FileSystemResource(file));
}
返回到
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents
// 获取所有 class 文件转为 Resource对象,见上
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
// 获取class文件中所有的注解信息,封装到 MetadataReader 对象中
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
// isCandidateComponent 过滤class文件上的所有的注解,即判断类上是否有 @Component、@Service、@Controller 等注解
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
// 将注解的 BeanDefinition 对象添加到集合中
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
MetadataReader 类中有 AnnotationMetadata getAnnotationMetadata(); 方法,可以获取类中的所有注解
isCandidateComponent 方法过滤所有的注解,即判断类上是否有 @Component、@Service、@Controller 等注解,如果有则创建一个 ScannedGenericBeanDefinition ,将注解信息封装成 BeanDefinition 对象中
返回到
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
for (String basePackage : basePackages) {
// 返回每个类中的注解封装的BeanDefinition 对象集合
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 循环 BeanDefinition
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);
}
// 是 AnnotatedBeanDefinition 类型时
if (candidate instanceof AnnotatedBeanDefinition) {
// 解析注解的相关属性值 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition)
processCommonDefinitionAnnotations(abd, abd.getMetadata());
org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition, org.springframework.core.type.AnnotatedTypeMetadata)
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"));
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
返回到
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
if (checkCandidate(beanName, candidate)) {
// BeanDefinition 封装成 BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册 BeanDefinition
registerBeanDefinition(definitionHolder, this.registry);
}
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#registerBeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// ....
//缓存 beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// beanDefinitionNames 集合中添加 beanName
this.beanDefinitionNames.add(beanName);
注解的 beanDefinition 注册完毕,注册 beanDefinition 其实就是将 beanDefinition 对象缓存在 DefaultListableBeanFactory 类中的 一些集合中
返回到
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse
// 注解的 beanDefinition 集合
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#registerComponents
// 兼容 annotation-config 标签配置
boolean annotationConfig = true;
if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
}
//
if (annotationConfig) {
Set<BeanDefinitionHolder> processorDefinitions =
// 注册相关注解的支持处理类,如 @Autowired、@Required 、@Configuration 等注解
AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
}
}
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
// @Order 注解的支持
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
// @Lazy 注解的支持
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// @Configuration 注解的支持
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
// @Autowired 注解的支持
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
// 注册 PostProcessor 处理器,查看该方法
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
// @Required 注解的支持
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
// @Resource 注解的支持 JSR-250
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
// JPA 注解的支持
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
// @EventListener 注解的支持
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
org.springframework.context.annotation.AnnotationConfigUtils#registerPostProcessor
// 这里是对注解 @Autowired 的 BeanDefinition 对象(上面的那个)进行注册
registry.registerBeanDefinition(beanName, definition);
// 返回 BeanDefinitionHolder
return new BeanDefinitionHolder(definition, beanName);
对 BeanDefinition 对象注册时都会进入到 org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition 方法中
返回到
org.springframework.context.annotation.ComponentScanBeanDefinitionParser#parse
总结:
<context:component-scan base-package="com.dn.spring.controller" >
标签在扫描配置的包时,会注册很多关于注解的相关处理器
<context:annotation-config/>
的处理器 org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser
里面其实注册了很多关于注解的处理器
总结
- 通过扫描指定包路径并加载 class 文件,将 class 文件转为 Resource对象
- 注册要扫描class文件中的注解,例如: @Component 注解 以及 @Component注解的子类,如@Service 等
- 过滤class文件上的所有的注解,即判断类上是否有 @Component、@Service、@Controller 等注解,将符合的 resource 封装为 ScannedGenericBeanDefinition 对象即 BeanDefinition
- 将 BeanDefinition 封装成 BeanDefinitionHolder 并进行注册,注册 beanDefinition 其实就是将 beanDefinition 对象缓存在 DefaultListableBeanFactory 类中的 一些集合中
- 注册相关注解的处理器类即BeanPostProcessor或BeanFactoryPostProcessor的子类,如 @Autowired、@Required 、@Configuration 等注解的解析和处理