流程
@Controller、@Service、@Repository的本质是@Component
注解 AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(“XX.xx.xx”); context.getBean();1.AnnotationConfigApplicationContext
沿着AnnotationConfigApplicationContext的构造方法,看下Spring在源码层面又是如何处理标注了注解@Component的类:
public AnnotationConfigApplicationContext(String... basePackages) {
this();
//扫描指定的bean
scan(basePackages);
//初始化容器
refresh();
}
方法this()中,初始化了两个成员变量this.reader和this.scanner,既然在构造方法中这么刻意的初始化它们,很有可能这两个成员变量的初始化逻辑中
可以看到首先会初始化BeanDefinitionRegistry类型的成员变量registr
beanDefinitionRegistry接口是Spring容器底层实现的一个接口,封装了注册BeanDefinition以及其他关于BeanDefinition相关的操作。
public AnnotationConfigApplicationContext() {
//注册一些注解的后置处理器
this.reader = new AnnotatedBeanDefinitionReader(this);
//指定要扫描的过滤
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
//看看AnnotatedBeanDefinitionReader 主要做什么的
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
//
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
//初始化registry
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
//注册一些和注解相关的后置处理器BeanDefinition
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
AnnotationConfigUtils类中的方法registerAnnotationConfigProcessors
主要是注册一些类的BeanDefinition到Spring容器中 包括:
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor"; "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"; "org.springframework.context.annotation.internalCommonAnnotationProcessor"; "org.springframework.context.annotation.internalPersistenceAnnotationProcessor"; "org.springframework.context.event.internalEventListenerProcessor"; "org.springframework.context.event.internalEventListenerFactory"; beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
另外一个成员变量也就是this.scanner对应的ClassPathBeanDefinitionScanner的初始化:
设置环境变量组件environment及相应的资源加载器resourceLoader,最终我们还是看到了一些重要的逻辑,如方法registerDefaultFilters
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry;
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
registerDefaultFilters();
在方法registerDefaultFilters中,我们发现主要就是往集合includeFilters中注册一些AnnotationTypeFilter,而通过AnnotationTypeFilter的名称,我们大概可以知道这是一个注解过滤器,是用来过滤指定类型的注解的。
protected void registerDefaultFilters() {
//注册Component类型的注解过滤器
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
//注册javax.annotation.ManagedBean
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 {
//注册avax.inject.Named"
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.
}
}
2.Scan();
Spring接下来会把扫描的任务委托给成员变量this.scanner处理,而this.scanner刚刚我们也看到了它的初始化,实际类型为ClassPathBeanDefinitionScanner。
@Override
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.scanner.scan(basePackages);
}
首先通过成员变量this.registry的方法getBeanDefinitionCount,获取Spring容器当前已经注册BeanDefinition的个数。
然后在方法最后,用当前Spring容器中BeanDefinition的数量,减去初始Spring容器中BeanDefinition数量,得到本次方法执行时一共注册了多少个BeanDefinition。
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
doScan(basePackages);
方法doScan会遍历所有包路径,依次到这些包路径下扫描并加载BeanDefinition,
protected SetdoScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set beanDefinitions = new LinkedHashSet<>();、 //遍历每个包路径 for (String basePackage : basePackages) { //在包路径下,加载符合条件的beanDefinitions Set candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { //获取beanDefinitions的 注解@Scope的元数据信息 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); //设置beanDefinitions的作用域为单例 candidate.setScope(scopeMetadata.getScopeName()); //生成bean的名称 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { //为beanDefinitions注册一些默认的属性值 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { //为其他各种注解上的信息,设置在beanDefinitions AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //判断当前的candiate,和容器中已经注册的beanDefinitions是否兼容 if (checkCandidate(beanName, candidate)) { //将beanDefinitions和beanName封装到BeanDefinitionHolder BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //注册BeanDefinitionHolder在spring容器中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
findCandidateComponents()
方法scanCandidateComponents果然开始扫描指定路径下的类了,首先会对我们传进去的包路径basePackage进行一些拼接处理,其中,ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX的值为“classpath*”,this.resourcePattern默认值为“***.class,也就是扫描该路径下的所有类,每个类我们都可以得到相应的资源Resource。
public SetfindCandidateComponents(String basePackage) { if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); } } private Set scanCandidateComponents(String basePackage) { Set candidates = new LinkedHashSet<>(); try { //加载路径下的所有资源 String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (resource.isReadable()) { try { //将resource封装到MetadataReader中,MetadataReader为资源Resource访问组件 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); //判断当前的Resouce是否符合条件 if (isCandidateComponent(metadataReader)) { //metadataReader封装到ScannedGenericBeanDefinition 类型的BeanDefinition ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setSource(resource); //判断ScannedGenericBeanDefinition当前的属否符合条件 if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } } return candidates; }
isCandidateComponent()
Spring是通过注解过滤器来过滤资源的,可以看到方法中会通过封装了注解过滤器的集合this.includeFilters,来过滤封装了Resource的MetadataReader。
因为this.includeFilter中添加了注解@Component的过滤器,所以,这里只会将标注了@Component注解的类给留下来,而成员变量this.excludeFilters很明显也是用来存放注解的过滤器,只不过它存放的注解过滤器,是用来剔除掉指定类型的注解过滤器的。
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;
}



