简介
前面介绍了scanner可以扫描某个包路径下的所有bean,我们最常用的也是通过ComponentScan指定包路径去扫描,在SpringBoot中也是如此,本文将介绍spring扫描的逻辑
BeanDefinitionRegistryPostProcessor
知道了ComponentScan的作用,那么spring什么时候开始解析ComponentScan去扫描bean呢
这个时候就要知道spring的其中一个生命周期 BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
该生命周期可以说是最早的一个,还在BeanFactoryPostProcessor#postProcessBeanFactory之前执行
从接口提供的方法就很明确,可以自己去注册一些bean
那么在该接口实现类里面就可以将最开始注册的AppConfig类拿出来,确定有ComponentScan注解,就可以拿到路径去扫描,最终注册bean
ConfigurationClassPostProcessor
ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor
在spring中通过该类进行配置类的解析,并且注册bean,只不过在spring中,标名是一个配置类的注解多种多样 ComponentScan 也只是其中一个
本文主要讲 ComponentScan 其它配置类后面讲
注册
源码链路
-
AnnotationConfigApplicationContext(Class<?>… componentClasses) # 进入this()
-
AnnotationConfigApplicationContext()
-
AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)
-
AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)
-
AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)
-
AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)
可以看到这么一行 注册ConfigurationClassPostProcessor
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
获取注册的ConfigurationClassPostProcessor
进入refresh方案,spring最重要的一个方法,整个生命周期都在这
- AnnotationConfigApplicationContext(Class<?>… componentClasses) # 进入this()
- AbstractApplicationContext#refresh()
- AbstractApplicationContext.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory); 处理
BeanFactory的后置处理器 - PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory,
List beanFactoryPostProcessors)
会看到如下代码
// 获取BeanDefinitionRegistryPostProcessor,一般来说就只有一个 ConfigurationClassPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}
}
// 排个序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行 BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();// 扫描完之后还有可能生成BeanFactoryPostProcessor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {// 过滤之前执行过的BeanFactoryPostProcessorif (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
以上就是获取 ConfigurationClassPostProcessor 到执行它的 postProcessBeanDefinitionRegistry方法的
逻辑,通过beanFactory.getBeanNamesForType 获取 BeanDefinitionRegistryPostProcessor
将获取到的BeanDefinitionRegistryPostProcessor 排个序,通过@Order注解或者@javax.annotation.Priority注解确定排序
遍历执行postProcessBeanDefinitionRegistry方法
解析 ComponentScan
那么在ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry又是怎么解析ComponentScan注册bean呢
- ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
- ConfigurationClassPostProcessor#processConfigBeanDefinitions(BeanDefinitionRegistry registry)
在这里会有一个检查,判断是不是配置类 ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef,
this.metadataReaderFactory)
那么什么是配置类呢,
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {// getFactoryMethodName表示是@Bean方式注入的bean,这种不作为配置类String className = beanDef.getBeanClassName();// 注解信息,通过MetadataReader获取(ASM技术) 并没有加载类AnnotationMetadata metadata;// 如果AnnotatedBeanDefinition,则直接取AnnotationMetadataif (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();}// 如果是AbstractBeanDefinition,则解析beanClass得到AnnotationMetadataelse if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {metadata = AnnotationMetadata.introspect(beanClass);}else {// ASM技术,这里其实也是spring提供的一个工具,我们也可以使用,后续文章介绍MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);metadata = metadataReader.getAnnotationMetadata();}Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());// 存在@Configuration,并且proxyBeanMethods不为false,就是配置类 配置类型为Fullif (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {// 设置属性configurationClass,表示是配置类beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);}// 存在@Configuration,并且proxyBeanMethods为false时,也是配置类配置类型为lite// 不存在@Configuration,存在@Component、@ComponentScan、@Import、@ImportResource中的某一个,也是配置类 配置类型为lite// 有@Bean标注的方法也是配置类else if (config != null || isConfigurationCandidate(metadata)) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);}else {return false;}// It's a full or lite configuration candidate... Let's determine the order value, if any.Integer order = getOrder(metadata);if (order != null) {// 配置类也可以排序,使用 Order注解beanDef.setAttribute(ORDER_ATTRIBUTE, order);}return true;}
private static final Set<String> candidateIndicators = new HashSet<>(8);static {candidateIndicators.add(Component.class.getName());candidateIndicators.add(ComponentScan.class.getName());candidateIndicators.add(Import.class.getName());candidateIndicators.add(ImportResource.class.getName());}public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {// 接口不管if (metadata.isInterface()) {return false;}// 只要存在@Component、@ComponentScan、@Import、@ImportResource四个中的一个,就是lite配置类for (String indicator : candidateIndicators) {if (metadata.isAnnotated(indicator)) {return true;}}// Finally, let's look for @Bean methods...// 只要存在@Bean注解了的方法,就是lite配置类return hasBeanMethods(metadata);
}
根据上面的代码逻辑分析,拥有@Configuration @Component、@ComponentScan、@Import、@ImportResource
或者方法有@Bean注解,那么就是一个配置类,继续后面代码分析
- parser.parse(candidates); candidates 就是找出的所有配置累会进入 ConfigurationClassParser#parse(AnnotationMetadata
metadata, String beanName) - ConfigurationClassParser#processConfigurationClass(ConfigurationClass configClass, Predicate filter)
- ConfigurationClassParser#doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass,
Predicate filter)
其它配置类先不看,那么会看到会看到如下代码
// 查看是否有ComponentScan注解
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for (AnnotationAttributes componentScan : componentScans) {// The config class is annotated with @ComponentScan -> perform the scan immediatelySet<BeanDefinitionHolder> scannedBeanDefinitions =this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());// Check the set of scanned definitions for any further config classes and parse recursively if neededfor (BeanDefinitionHolder holder : scannedBeanDefinitions) {BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();if (bdCand == null) {bdCand = holder.getBeanDefinition();}// 解析出来还有配置类,继续解析if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {parse(bdCand.getBeanClassName(), holder.getBeanName());}}}
}
查看该Bean的有没有ComponentScans或者ComponentScan注解,如果有那么使用ComponentScanAnnotationParser解析
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);// bean的名字生成器,默认是首字母小写的类名,可以自己定义其它规则,比如类的全限定名Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);// 默认为AnnotationBeanNameGeneratorscanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :BeanUtils.instantiateClass(generatorClass));// 默认就是扫描包下面的class文件scanner.setResourcePattern(componentScan.getString("resourcePattern"));for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {for (TypeFilter typeFilter : typeFiltersFor(filter)) {scanner.addIncludeFilter(typeFilter);}}for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {for (TypeFilter typeFilter : typeFiltersFor(filter)) {scanner.addExcludeFilter(typeFilter);}}boolean lazyInit = componentScan.getBoolean("lazyInit");if (lazyInit) {scanner.getBeanDefinitionDefaults().setLazyInit(true);}Set<String> basePackages = new LinkedHashSet<>();String[] basePackagesArray = componentScan.getStringArray("basePackages");for (String pkg : basePackagesArray) {String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);Collections.addAll(basePackages, tokenized);}for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {basePackages.add(ClassUtils.getPackageName(clazz));}if (basePackages.isEmpty()) {basePackages.add(ClassUtils.getPackageName(declaringClass));}scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {@Overrideprotected boolean matchClassName(String className) {// 排除掉自己return declaringClass.equals(className);}});// 开始扫描,注册beanreturn scanner.doScan(StringUtils.toStringArray(basePackages));}
以上就是如何解析ComponentScan的逻辑,解析完后,开始扫描,进行BeanDefinition注册,注意是BeanDefinition注册,还不是实例化bean
- ClassPathBeanDefinitionScanner#doScan
- ClassPathBeanDefinitionScanner#registerBeanDefinition
- BeanDefinitionReaderUtils#registerBeanDefinition
- DefaultListableBeanFactory#registerBeanDefinition
最终存放在 beanDefinitionMap beanDefinitionNames
记住这两个属性,特别重要
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private volatile List beanDefinitionNames = new ArrayList<>(256);
以上就是通过ComponentScan注解注册Bean的逻辑了,其它配置类以及实例化bean的逻辑后面文章在介绍
欢迎关注,学习不迷路!