以下文章来源于http://8rr.co/EjqL,作者温安适
前言@Component和@Service都是工作中常用的注解,Spring如何解析?
1.@Component解析流程Spring Framework2.0开始,引入可扩展的XML编程机制,该机制要求XML Schema命名空间需要与Handler建立映射关系。
该关系配置在相对于classpath下的/META-INF/spring.handlers中。
如上图所示 ContextNamespaceHandler对应<...> 分析的入口。
找核心方法
浏览ContextNamespaceHandler
在parse中有一个很重要的注释
// Actually scan for bean definitions and register them.
ClassPathBeanDefinitionScanner scanner &#61; configureScanner(parserContext, element);
大意是&#xff1a;ClassPathBeanDefinitionScanner#doScan是扫描BeanDefinition并注册的实现。
ClassPathBeanDefinitionScanner 的源码如下&#xff1a;
protected Set doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set beanDefinitions &#61; new LinkedHashSet<>();for (String basePackage : basePackages) {//findCandidateComponents 读资源转换为BeanDefinition
Set candidates &#61; findCandidateComponents(basePackage);for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata &#61; this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName &#61; this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder &#61; new BeanDefinitionHolder(candidate, beanName);
definitionHolder &#61;
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}return beanDefinitions;
}
上边的代码&#xff0c;从方法名&#xff0c;猜测&#xff1a;
findCandidateComponents&#xff1a;从classPath扫描组件&#xff0c;并转换为备选BeanDefinition&#xff0c;也就是要做的解析&#64;Component的核心方法。
findCandidateComponents在其父类ClassPathScanningCandidateComponentProvider 中。
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
//省略其他代码
public Set findCandidateComponents(String basePackage) {
if (this.componentsIndex !&#61; null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}
private Set scanCandidateComponents(String basePackage) {
Set candidates &#61; new LinkedHashSet<>();try {
String packageSearchPath &#61; ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX &#43;
resolveBasePackage(basePackage) &#43; &#39;/&#39; &#43; this.resourcePattern;
Resource[] resources &#61; getResourcePatternResolver().getResources(packageSearchPath);//省略部分代码for (Resource resource : resources) {//省略部分代码if (resource.isReadable()) {try {
MetadataReader metadataReader &#61; getMetadataReaderFactory().getMetadataReader(resource);if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd &#61; new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);if (isCandidateComponent(sbd)) {
candidates.add(sbd);//省略部分代码
}
}catch (IOException ex) {//省略部分代码 }return candidates;
}
}
findCandidateComponents大体思路如下&#xff1a;
ClassPathScanningCandidateComponentProvider#isCandidateComponent其源码如下&#xff1a;
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
//省略部分代码
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
includeFilters由registerDefaultFilters()设置初始值&#xff0c;有&#64;Component&#xff0c;没有&#64;Service啊&#xff1f;
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl &#61; ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 &#39;javax.annotation.ManagedBean&#39; 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 &#39;javax.inject.Named&#39; annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
Spring如何处理&#64;Service的注解的呢&#xff1f;&#xff1f;&#xff1f;&#xff1f;
查阅官方文档&#xff0c;下面这话&#xff1a;
https://docs.spring.io/spring/docs/5.0.17.RELEASE/spring-framework-reference/core.html#beans-meta-annotations
&#64;Component is a generic stereotype for any Spring-managed component. &#64;Repository, &#64;Service, and &#64;Controller are specializations of &#64;Component
大意如下&#xff1a;
&#64;Component是任何Spring管理的组件的通用原型。&#64;Repository、&#64;Service和&#64;Controller是派生自&#64;Component。
&#64;Target({ElementType.TYPE})
&#64;Retention(RetentionPolicy.RUNTIME)
&#64;Documented
// &#64;Service 派生自&#64;Component
&#64;Component
public &#64;interface Service {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* &#64;return the suggested component name, if any (or empty String otherwise)
*/
&#64;AliasFor(annotation &#61; Component.class)
String value() default "";
}
&#64;Component是&#64;Service的元注解&#xff0c;Spring 大概率&#xff0c;在读取&#64;Service&#xff0c;也读取了它的元注解&#xff0c;并将&#64;Service作为&#64;Component处理。
3. 探寻&#64;Component派生性流程回顾ClassPathScanningCandidateComponentProvider 中的关键的代码片段如下&#xff1a;
private Set scanCandidateComponents(String basePackage) {
//省略其他代码
MetadataReader metadataReader
&#61;getMetadataReaderFactory().getMetadataReader(resource);
if(isCandidateComponent(metadataReader)){
//....
}
}
public final MetadataReaderFactory getMetadataReaderFactory() {
if (this.metadataReaderFactory &#61;&#61; null) {
this.metadataReaderFactory &#61; new CachingMetadataReaderFactory();
}
return this.metadataReaderFactory;
}
CachingMetadataReaderFactory继承自 SimpleMetadataReaderFactory&#xff0c;就是对SimpleMetadataReaderFactory加了一层缓存。
其内部的SimpleMetadataReaderFactory#getMetadataReader 为&#xff1a;
public class SimpleMetadataReaderFactory implements MetadataReaderFactory {
&#64;Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
}
这里可以看出
MetadataReader metadataReader &#61;new SimpleMetadataReader(...);
AnnotationTypeFilter#matchself方法如下&#xff1a;
&#64;Override
protected boolean matchSelf(MetadataReader metadataReader) {
AnnotationMetadata metadata &#61; metadataReader.getAnnotationMetadata();
return metadata.hasAnnotation(this.annotationType.getName()) ||
(this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
}
是metadata.hasMetaAnnotation法&#xff0c;从名称看是处理元注解&#xff0c;我们重点关注
metadata&#61;metadataReader.getAnnotationMetadata();
metadataReader &#61;new SimpleMetadataReader(...)
metadata&#61; new SimpleMetadataReader#getAnnotationMetadata()
//SimpleMetadataReader 的构造方法
SimpleMetadataReader(Resource resource, &#64;Nullable ClassLoader classLoader) throws IOException {
InputStream is &#61; new BufferedInputStream(resource.getInputStream());
ClassReader classReader;
try {
classReader &#61; new ClassReader(is);
}
catch (IllegalArgumentException ex) {
throw new NestedIOException("ASM ClassReader failed to parse class file - " &#43;
"probably due to a new Java class file version that isn&#39;t supported yet: " &#43; resource, ex);
}
finally {
is.close();
}
AnnotationMetadataReadingVisitor visitor &#61;
new AnnotationMetadataReadingVisitor(classLoader);
classReader.accept(visitor, ClassReader.SKIP_DEBUG);
this.annotationMetadata &#61; visitor;
// (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor)
this.classMetadata &#61; visitor;
this.resource &#61; resource;
}
metadata&#61;new SimpleMetadataReader(...)**.**getAnnotationMetadata()&#61; new AnnotationMetadataReadingVisitor(。。)
也就是说
metadata.hasMetaAnnotation&#61;AnnotationMetadataReadingVisitor#hasMetaAnnotation
其方法如下&#xff1a;
public class AnnotationMetadataReadingVisitor{
// 省略部分代码
&#64;Override
public boolean hasMetaAnnotation(String metaAnnotationType) {
Collection> allMetaTypes &#61; this.metaAnnotationMap.values();for (Set metaTypes : allMetaTypes) {if (metaTypes.contains(metaAnnotationType)) {return true;
}
}return false;
}
}
逻辑很简单&#xff0c;就是判断该注解的元注解在&#xff0c;在不在metaAnnotationMap中&#xff0c;如果在就返回true。
这里面核心就是metaAnnotationMap&#xff0c;搜索AnnotationMetadataReadingVisitor类&#xff0c;没有发现赋值的地方&#xff1f;&#xff1f;&#xff01;。
回到SimpleMetadataReader 的方法&#xff0c;
//这个accept方法&#xff0c;很可疑&#xff0c;在赋值之前执行
SimpleMetadataReader(Resource resource, &#64;Nullable ClassLoader classLoader) throws IOException {
//省略其他代码
AnnotationMetadataReadingVisitor visitor &#61; new AnnotationMetadataReadingVisitor(classLoader);
classReader.accept(visitor, ClassReader.SKIP_DEBUG);
this.annotationMetadata &#61; visitor;
}
发现一个可疑的语句&#xff1a;classReader.accept。
查看accept方法
public class ClassReader {
//省略其他代码
public void accept(..省略代码){
//省略其他代码
readElementValues(
classVisitor.visitAnnotation(annotationDescriptor, /* visible &#61; */ true),
currentAnnotationOffset,
true,
charBuffer);
}
}
查看readElementValues方法
public class ClassReader{
//省略其他代码
private int readElementValues(final AnnotationVisitor annotationVisitor,final int annotationOffset,final boolean named,final char[] charBuffer) {
int currentOffset &#61; annotationOffset;
// Read the num_element_value_pairs field (or num_values field for an array_value).
int numElementValuePairs &#61; readUnsignedShort(currentOffset);
currentOffset &#43;&#61; 2;
if (named) {
// Parse the element_value_pairs array.
while (numElementValuePairs-- > 0) {
String elementName &#61; readUTF8(currentOffset, charBuffer);
currentOffset &#61;
readElementValue(annotationVisitor, currentOffset &#43; 2, elementName, charBuffer);
}
} else {
// Parse the array_value array.
while (numElementValuePairs-- > 0) {
currentOffset &#61;
readElementValue(annotationVisitor, currentOffset, /* named &#61; */ null, charBuffer);
}
}
if (annotationVisitor !&#61; null) {
annotationVisitor.visitEnd();
}
return currentOffset;
}
}
这里面的核心就是 annotationVisitor.visitEnd();
这里的annotationVisitor&#61;AnnotationMetadataReadingVisitor#visitAnnotation
源码如下&#xff0c;注意这里传递了metaAnnotationMap&#xff01;&#xff01;
public class AnnotationMetadataReadingVisitor{
&#64;Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
String className &#61; Type.getType(desc).getClassName();
this.annotationSet.add(className);
return new AnnotationAttributesReadingVisitor(
className, this.attributesMap,
this.metaAnnotationMap, this.classLoader);
}
}
annotationVisitor&#61;AnnotationAttributesReadingVisitor
annotationVisitor&#61;AnnotationAttributesReadingVisitor#visitEnd()
public class AnnotationAttributesReadingVisitor{
&#64;Override
public void visitEnd() {
super.visitEnd();
Class extends Annotation> annotationClass &#61; this.attributes.annotationType();
if (annotationClass !&#61; null) {
List attributeList &#61; this.attributesMap.get(this.annotationType);if (attributeList &#61;&#61; null) {this.attributesMap.add(this.annotationType, this.attributes);
}else {
attributeList.add(0, this.attributes);
}if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationClass.getName())) {try {
Annotation[] metaAnnotations &#61; annotationClass.getAnnotations();if (!ObjectUtils.isEmpty(metaAnnotations)) {
Set visited &#61; new LinkedHashSet<>();for (Annotation metaAnnotation : metaAnnotations) {
recursivelyCollectMetaAnnotations(visited, metaAnnotation);
}if (!visited.isEmpty()) {
Set metaAnnotationTypeNames &#61; new LinkedHashSet<>(visited.size());for (Annotation ann : visited) {
metaAnnotationTypeNames.add(ann.annotationType().getName());
}this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
}
}
}catch (Throwable ex) {if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect meta-annotations on " &#43; annotationClass &#43; ": " &#43; ex);
}
}
}
}
}
}
内部方法recursivelyCollectMetaAnnotations 递归的读取注解&#xff0c;与注解的元注解(读&#64;Service&#xff0c;再读元注解&#64;Component)&#xff0c;并设置到metaAnnotationMap&#xff0c;也就是AnnotationMetadataReadingVisitor 中的metaAnnotationMap中。
总结大致如下&#xff1a;
ClassPathScanningCandidateComponentProvider#findCandidateComponents
将package转化为ClassLoader类资源搜索路径packageSearchPath
加载搜素路径下的资源。
isCandidateComponent 判断是否是备选组件。
内部调用的TypeFilter的match方法&#xff1a;
AnnotationTypeFilter#matchself中metadata.hasMetaAnnotation处理元注解
metadata.hasMetaAnnotation&#61;AnnotationMetadataReadingVisitor#hasMetaAnnotation
就是判断当前注解的元注解在不在metaAnnotationMap中。
AnnotationAttributesReadingVisitor#visitEnd()内部方法recursivelyCollectMetaAnnotations 递归的读取注解&#xff0c;与注解的元注解(读&#64;Service&#xff0c;再读元注解&#64;Component)&#xff0c;并设置到metaAnnotationMap