我们都知道只要给对应的类添加相应的注解(@Repository@Service@Controller@Component),spring就可以把类作为bean注入到ioc容器里。另外@Bean注解也可以把方法作为一个bean注入。
目录
一、@Repository@Service@Controller@Component
findCandidateComponents(basePackage);
二、@Bean
总结
一、@Repository@Service@Controller@Component
这些都是我们常用的注解,既然是注解,我们在AnnotationConfigUtils抽象类中找到入口。
AnnotationConfigUtils#registerAnnotationConfigProcessors 方法,这个方法是spring添加一些注解对应的处理器,spring的事件监听注解也是在这里注册的。
ConfigurationClassPostProcessor 是配置注解的处理器。
主要看ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry方法,这个方法是BeanDefinitionRegistryPostProcessor接口的实现。
获取已经注册的beanName进行循环,String[] candidateNames = registry.getBeanDefinitionNames(); 其中就包括项目的启动类
其中ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) 方法是检查是否有@Component@Configuration之类的注解,有的话就添加到集合里下一步处理。这里我们debug可以看到,最后这个集合里就是我项目的启动类。
然后下面进入到do.while循环,
重点看 parser.parse(candidates); 这个方法就是去找对应的注解,一些Service,Controller等注解并注册到ico容器。
this.reader.loadBeanDefinitions(configClasses); 这个方法是为@Bean注解注册到ioc容器。下面讲解
我们先看parser.parse(candidates); 方法的实现
doProcessConfigurationClass方法
protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter) throws IOException { if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // Recursively process any member (nested) classes first processMemberClasses(configClass, sourceClass, filter); } // Process any @PropertySource annotations for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // 可以理解为判断有没有@ComponentScan,ComponentScans注解 Set componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // 主要功能去解析指定包下的所以class文件是否有相应的注解,并返回BeanDefinitionHolder集合 Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // 返回的集合是否有任何进一步的配置类,并在需要时进行递归解析 for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } //判断是否有@Component@Service@Controller等注解,继续递归解析 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // 处理 @Import注解 processImports(configClass, sourceClass, getImports(sourceClass), filter, true); //处理 @ImportResource 注解 AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { String[] resources = importResource.getStringArray("locations"); Class extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); for (String resource : resources) { String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } // 处理 @Bean 注解 Set beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { //添加对象,后面从这里获取解析 configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces processInterfaces(configClass, sourceClass); // Process superclass, if any if (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) { this.knownSuperclasses.put(superclass, configClass); // Superclass found, return its annotation metadata and recurse return sourceClass.getSuperClass(); } } // No superclass -> processing is complete return null; }
方法Set
调用ComponentScanAnnotationParser解析器去解析
ComponentScanAnnotationParser#parse 方法最后去扫描
根据包名来扫描 ClassPathBeanDefinitionScanner#doScan
终于来到Set
这个方法就是扫描拿到了满足条件的类,然后循环进行下面的注册。并返回BeanDefinitionHolder集合。
中间链路太长了,中间的类型判断,类型转换等等。不过没关系,我们终究还是来到了。
findCandidateComponents(basePackage);
private SetscanCandidateComponents(String basePackage) { Set candidates = new LinkedHashSet<>(); try { //转成classpath // classpath*:com/example/demo*.class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; //获取当前包下所有的class文件 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { //通过ASM 获取class文件的注解,并递归解析父级的注解来合并成mappings数组。封装成元数据对象 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); //判断注解是否在includeFilters集合里面 if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setSource(resource); //检查是否抽象类,是否接口 if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } //加入BeanDefinition集合并返回,注入ioc 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; }
getMetadataReaderFactory().getMetadataReader(resource);
调用工厂获取一个MetadataReader
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
//构造器,创建了一个SimpleAnnotationMetadataReadingVisitor访问者
SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader);
//二进制,字节码解析class文件获取注解信息,通过visitor回调
getClassReader(resource).accept(visitor, PARSING_OPTIONS);
this.resource = resource;
this.annotationMetadata = visitor.getMetadata();
}
这里使用了访问者设计模式,我们看一下visitEnd()回调方法
SimpleAnnotationMetadataReadingVisitor#visitEnd()
@Override
public void visitEnd() {
String[] memberClassNames = StringUtils.toStringArray(this.memberClassNames);
MethodMetadata[] annotatedMethods = this.annotatedMethods.toArray(new MethodMetadata[0]);
//根据当前注解获取父级的注解信息,生成MergedAnnotationsCollection对象,存了注解的并集,后面判断需要
MergedAnnotations annotations = MergedAnnotations.of(this.annotations);
this.metadata = new SimpleAnnotationMetadata(this.className, this.access,
this.enclosingClassName, this.superClassName, this.independentInnerClass,
this.interfaceNames, memberClassNames, annotatedMethods, annotations);
}
static MergedAnnotations of(Collection> annotations) { Assert.notNull(annotations, "Annotations must not be null"); if (annotations.isEmpty()) { return TypeMappedAnnotations.NONE; } //创建MergedAnnotationsCollection对象 return new MergedAnnotationsCollection(annotations); }
//构造器 private MergedAnnotationsCollection(Collection> annotations) { Assert.notNull(annotations, "Annotations must not be null"); //当前类上的注解 this.annotations = annotations.toArray(new MergedAnnotation>[0]); this.mappings = new AnnotationTypeMappings[this.annotations.length]; //循环每个注解,获取父级的注解,并加到mappings数组里。 for (int i = 0; i < this.annotations.length; i++) { MergedAnnotation> annotation = this.annotations[i]; Assert.notNull(annotation, "Annotation must not be null"); Assert.isTrue(annotation.isDirectlyPresent(), "Annotation must be directly present"); Assert.isTrue(annotation.getAggregateIndex() == 0, "Annotation must have aggregate index of zero"); this.mappings[i] = AnnotationTypeMappings.forAnnotationType(annotation.getType()); } }
到此MetadataReader创建完成,主要是存了class的注解信息。
isCandidateComponent(metadataReader)
判断是否有注解在includeFilters集合里,即是否有满足自动注入ioc的注解
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
//匹配,满足匹配返回
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
includeFilters集合里有两个注解 @Component @ManagedBean
为什么只有两个,按道理不应该是@Repository@Service@Controller@Component注解等等吗。那我们看下@Repository@Service@Controller的源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}
可以看到每个注解里都有一个@Component注解,即@Component是元注解,@Repository@Service@Controller都是@Component的派生注解。 所以在项目里要想注入到ico容器里,只要添加@Component注解就可以。
看匹配的方法是怎么匹配的,tf.match(metadataReader, getMetadataReaderFactory())
AbstractTypeHierarchyTraversingFilter#match
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//判断是否有@Component注解。因为tf的类型是AnnotationTypeFilter,所以matchSelf方法在AnnotationTypeFilter类里重写
if (matchSelf(metadataReader)) {
return true;
}
ClassMetadata metadata = metadataReader.getClassMetadata();
if (matchClassName(metadata.getClassName())) {
return true;
}
AnnotationTypeFilter#matchSelf
@Override
protected boolean matchSelf(MetadataReader metadataReader) {
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
return metadata.hasAnnotation(this.annotationType.getName()) ||
(this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
}
这里主要是两个判断:
metadata.hasAnnotation(this.annotationType.getName()) //判断当前类是否有@Component注解
metadata.hasMetaAnnotation(this.annotationType.getName()) //判断父级类有没有@Component注解
因为在上面创建元数据对象MetadataReader的时候分析,在访问者的visitEnd()回调方法里创建了MergedAnnotationsCollection对象,里面存了当前类的注解信息。
所以看下在MergedAnnotationsCollection里是怎么判断的。
MergedAnnotationsCollection#isDirectlyPresent
@Override
public boolean isDirectlyPresent(String annotationType) {
return isPresent(annotationType, true);
}
private boolean isPresent(Object requiredType, boolean directOnly) {
//判断this.annotations当前class上是否有@Component注解
for (MergedAnnotation> annotation : this.annotations) {
Class extends Annotation> type = annotation.getType();
if (type == requiredType || type.getName().equals(requiredType)) {
return true;
}
}
//directOnly 为 true ,不走下面
if (!directOnly) {
for (AnnotationTypeMappings mappings : this.mappings) {
for (int i = 1; i < mappings.size(); i++) {
AnnotationTypeMapping mapping = mappings.get(i);
if (isMappingForType(mapping, requiredType)) {
return true;
}
}
}
}
return false;
}
MergedAnnotationsCollection#find
private MergedAnnotation find(Object requiredType,
@Nullable Predicate super MergedAnnotation> predicate,
@Nullable MergedAnnotationSelector selector) {
if (selector == null) {
selector = MergedAnnotationSelectors.nearest();
}
MergedAnnotation result = null;
for (int i = 0; i < this.annotations.length; i++) {
MergedAnnotation> root = this.annotations[i];
AnnotationTypeMappings mappings = this.mappings[i];
//循环mappings 数组---里面是所有父级的注解
for (int mappingIndex = 0; mappingIndex < mappings.size(); mappingIndex++) {
AnnotationTypeMapping mapping = mappings.get(mappingIndex);
//判断是否有@Component注解
if (!isMappingForType(mapping, requiredType)) {
continue;
}
MergedAnnotation candidate = (mappingIndex == 0 ? (MergedAnnotation) root :
TypeMappedAnnotation.createIfPossible(mapping, root, IntrospectionFailureLogger.INFO));
if (candidate != null && (predicate == null || predicate.test(candidate))) {
if (selector.isBestCandidate(candidate)) {
return candidate;
}
result = (result != null ? selector.select(result, candidate) : candidate);
}
}
}
return result;
}
判断完成,返回BeanDefinition集合,注入ioc
二、@Bean
在上面的分析中,我们在ConfigurationClassParser#doProcessConfigurationClass 方法中看到了bean注解的解析
// 处理 @Bean methods SetbeanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { //把有@Bean注解的方法创建beanMethods对象,并加到beanMethods集合里缓存。等全部类解析完后在外面注入 configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); }
private SetretrieveBeanMethodMetadata(SourceClass sourceClass) { AnnotationMetadata original = sourceClass.getMetadata(); //在元数据里获取有Bean注解的方法 Set beanMethods = original.getAnnotatedMethods(Bean.class.getName()); if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) { // Try reading the class file via ASM for deterministic declaration order... // Unfortunately, the JVM's standard reflection returns methods in arbitrary // order, even between different runs of the same application on the same JVM. try { AnnotationMetadata asm = this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata(); Set asmMethods = asm.getAnnotatedMethods(Bean.class.getName()); if (asmMethods.size() >= beanMethods.size()) { Set selectedMethods = new LinkedHashSet<>(asmMethods.size()); for (MethodMetadata asmMethod : asmMethods) { for (MethodMetadata beanMethod : beanMethods) { if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) { selectedMethods.add(beanMethod); break; } } } if (selectedMethods.size() == beanMethods.size()) { // All reflection-detected methods found in ASM method set -> proceed beanMethods = selectedMethods; } } } catch (IOException ex) { logger.debug("Failed to read class file via ASM for determining @Bean method order", ex); // No worries, let's continue with the reflection metadata we started with... } } return beanMethods; }
回到最开始的注解配置处理器ConfigurationClassPostProcessor
ConfigurationClassPostProcessor#processConfigBeanDefinitions
do while循环里
do {
//解析class的注解
parser.parse(candidates);
parser.validate();
Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//注入返回的类集合里的有@Bean注解的方法
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
this.reader.loadBeanDefinitions(configClasses);
public void loadBeanDefinitions(SetconfigurationModel) { TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); for (ConfigurationClass configClass : configurationModel) { loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } }
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//取出缓存@Bean方法的集合,循环
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
循环进去loadBeanDefinitionsForBeanMethod(beanMethod)方法
方法的最后注入ioc容器。
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
总结
主要类的调用顺序
ConfigurationClassPostProcessor ==》ConfigurationClassParser ==》ComponentScanAnnotationParser ==》ClassPathBeanDefinitionScanne ==》ClassPathScanningCandidateComponentProvider
主要方法 :
Set
tf.match(metadataReader, getMetadataReaderFactory()) 注解匹配的方法
通过指定的包路径,扫描所有的class文件,asm字节码解析获取class的注解信息封装成MetadataReader,并通过MergedAnnotationsCollection递归合并父级的注解,最后判断class是否满足注入ico容器,即有没有@Component注解。
中间还解析了@Bean注解的方法。返回所有满足的方法并注入ioc。
this.reader.loadBeanDefinitions(configClasses); //注入@bean注解的bean



