赞
踩
解析启动类流程主要分为三大块:解析类路径下用户自定义的所有类、解析SPI机制从spring.factories文件中加载获取到的类、以及创建所有候选类的BeanDefinitions「用户自定义的类在扫描包路径时触发BeanDefinitions的初始化、spring.factories文件中的候选类以及其间接加载的候选类单独触发BeanDefinitions的初始化」。
- public class ConfigurationClassPostProcessor{
-
- public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
-
- ...
- do {
- //ConfigurationClassParser#parse
- parser.parse(candidates);
- parser.validate();
- ...
- }
- ...
- // ===================== 注册自动装配候选类以及其@bean注解对应BeanDefinition至bean工厂中
- // 参考第7节
- this.reader.loadBeanDefinitions(configClasses);
- while (!candidates.isEmpty());
- }
- }
AnnotatedGenericBeanDefinition类型的BeanDefinition。这种类型的BeanDefinition提供基于元数据、元注解分析的StandardAnnotationMetadata。
由于SpringBoot启动过程中存在诸多元数据、元注解的解析,其中AnnotatedGenericBeanDefinition类型的BeanDefinition初始化了ClassMetadata、AnnotatedTypeMetadata两种类型解析器StandardAnnotationMetadata
ImportSelector延迟类型之DeferredImportSelector:加载类路径下自动装配的全部候选类,并且解析每一个候选类是否存在@Component、@ComponentScans、@Import等相关注解。
- class ConfigurationClassParser {
-
- private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();
-
-
- public void parse(Set<BeanDefinitionHolder> configCandidates) {
- for (BeanDefinitionHolder holder : configCandidates) {
- BeanDefinition bd = holder.getBeanDefinition();
- try {
- if (bd instanceof AnnotatedBeanDefinition) {
- parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
- }
- ...
- }
- }
- //【自定义类处理完毕】===========================延迟类型的ImportSelector处理器
- this.deferredImportSelectorHandler.process();
- }
-
- //metadata:StandardAnnotationMetadata
- protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
- processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
- }
-
-
- protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
-
- if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
- return;
- }
- // 此处存在去重逻辑,避免重复处理候选类
- ConfigurationClass existingClass = this.configurationClasses.get(configClass);
- ...
- // Recursively process the configuration class and its superclass hierarchy.
- SourceClass sourceClass = asSourceClass(configClass, filter);
- do {
- sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
- }
- while (sourceClass != null);
-
- this.configurationClasses.put(configClass, configClass);
- }
-
- @Nullable
- protected SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter){
-
- if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
- // Recursively process any member (nested) classes first
- processMemberClasses(configClass, sourceClass, filter);
- }
-
- // Process any @PropertySource annotations
- ...
- // Process any @ComponentScan annotations
- AnnotationMetadata am = sourceClass.getMetadata();
- Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(am, ComponentScans.class, ComponentScan.class);
- if (!componentScans.isEmpty() && !conditionEvaluator.shouldSkip(am, ConfigurationPhase.REGISTER_BEAN)) {
- for (AnnotationAttributes componentScan : componentScans) {
- String className = sourceClass.getMetadata().getClassName();
- //==========================================将扫描类路径下得到的用户自定义类的BeanDefinition注册到 bean工厂中
- Set<BeanDefinitionHolder> scannedBeanDefinitions = componentScanParser.parse(componentScan, className);
- for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
- BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
- if (bdCand == null) {
- bdCand = holder.getBeanDefinition();
- }
- if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
- // 解析每个自定义类存在的@Component、@PropertySource、@ComponentScan...等注解
- parse(bdCand.getBeanClassName(), holder.getBeanName());
- }
- }
- }
- }
-
- // Process any @Import annotations
- processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
-
- // Process any @ImportResource annotations
-
- // Process individual @Bean methods
- Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
- for (MethodMetadata methodMetadata : beanMethods) {
- configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
- }
- return null;
- }
-
- }
configCandidates:AnnotatedBeanDefinition类型的启动类。
shouldSkip:判断当前候选类是否存在Conditional注解。正常情况下启动类不存在的。
最终结果:符合条件的类最终都会添加到Map类型的集合ConfigurationClasses中。
涉及的注解解析流程如下:
SpringBoot中解析任何一个类「包括上述注解解析到的类」都会执行ConfigurationClassParser#processConfigurationClass方法。 就是因为每个候选类最终都会作为Map类型的集合ConfigurationClasses中元素。
deferredImportSelectorHandler.process:解析核心类AutoConfigurationImportSelector过程中利用SPI机制加载spring.factories文件中配置的候选的装配类。 这些装配类的解析同样会使用当前文的全文逻辑。具体参考
该接口的实现类【OnBeanCondition、OnClassCondition、OnPropertyCondition】等都存在一个用于排序的注解`@Order`。
@Order注解其value取值越大对应排序时的优先级越低。
使用方式之直接方式即`自定义实现接口Condition的子类 | 直接@Conditional`,间接方式之@Conditional:
通过组合注解方式使用时其@Conditional注解属性class【OnBeanCondition、OnClassCondition、OnPropertyCondition】都会对应的赋值实现接口Condition的子类。
作用:主要是利用接口Condition的功能判断【直接方式、间接方式】配置类是否满足条件。
主要解析的是当前类的元注解信息「AnnotatedTypeMetadata」。
如果返回true,当前类则不会添加到集合ConfigurationClasses中,也即Spring IOC容器中更不会存在。
如果这些注解存在于类内部的方法上【通常是协同@Bean注解】,符合条件的会将@Bean的bean定义信息添加到beanDefinitionMap。后续用于实例并初始化。
- class ConditionEvaluator {
-
- public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
- if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
- return false;
- }
- ...
- List<Condition> conditions = new ArrayList<>();
- for (String[] conditionClasses : getConditionClasses(metadata)) {
- for (String conditionClass : conditionClasses) {
- Condition condition = getCondition(conditionClass, this.context.getClassLoader());
- conditions.add(condition);
- }
- }
-
- AnnotationAwareOrderComparator.sort(conditions);
- for (Condition condition : conditions) {
- ConfigurationPhase requiredPhase = null;
- if (condition instanceof ConfigurationCondition) {
- requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
- }
- if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
- return true;
- }
- }
- return false;
- }
- }
如果当前类存在的组合注解中存在@Component注解都会触发。
memberClasses:获取当前类中的所有内部类。集合中所有内部类按照位置顺序从后往前依次添加到集合中。
- private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
- Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
- if (!memberClasses.isEmpty()) {
- List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
- for (SourceClass memberClass : memberClasses) {
- // 内部类成为候选类的条件
- if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
- !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
- candidates.add(memberClass);
- }
- }
- // 所有内部类排序,决定内部类触发的先后顺序
- OrderComparator.sort(candidates);
- for (SourceClass candidate : candidates) {
- ...
- processConfigurationClass(candidate.asConfigClass(configClass));
- }
- }
- }
- }
- public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
- if (metadata.isInterface()) {
- return false;
- }
- for (String indicator : candidateIndicators) {//4种类型注解:Import、ImportResuource、Component、ComponentScan
- if (metadata.isAnnotated(indicator)) {
- return true;
- }
- }
- return metadata.hasAnnotatedMethods(Bean.class.getName());
- }
- public class ClassPathScanningCandidateComponentProvider{
- static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
- String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
- private final List<TypeFilter> excludeFilters = new ArrayList<>();
- private final List<TypeFilter> includeFilters = new ArrayList<>();
- private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
- Set<BeanDefinition> candidates = new LinkedHashSet<>();
- // 获取到类路径下全部的类
- String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
- resolveBasePackage(basePackage) + '/' + this.resourcePattern;
- Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
- for (Resource resource : resources) {
- MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
- // 遍历每一个类,判断是否满足候选类特性
- if (isCandidateComponent(metadataReader)) {
- ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
- sbd.setSource(resource);
- if (isCandidateComponent(sbd)) {
- candidates.add(sbd);
- }
- }
- }
- return candidates;
- }
-
- 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;
- }
- }
默认情况下excludeFilters主要包含:AutoConfigurationExcludeFilter、TypeExcludeFilter。其中前者主要判断当前类是否存在注解@Configuration,后者应该是方便使用方自行扩展类的Filter。
默认情况下includeFilters主要包含:AnnotationTypeFilter,主要判断当前类是否存在注解@Component。
通常情况下候选类只要存在@Configuration、@Component任意一个注解都会被IOC容器自行管理的类。
通过@Import注解注入Bean的方式有如下三种:
- class ConfigurationClassParser {
-
- DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();
-
- private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
- Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
-
- for (SourceClass candidate : importCandidates) {// 当前类通过import注解导入的全部候选类
- // 候选类 是接口ImportSelector的子类
- if (candidate.isAssignable(ImportSelector.class)) {
- Class<?> candidateClass = candidate.loadClass();
- ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
- ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);
- // 候选类 同时也是 接口DeferredImportSelector的子类 -- 启动类注解import导入的AutoConfigurationImportSelector
- if (selector instanceof DeferredImportSelector) {
- this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
- }else {
- // 直接调用候选类核心方法之selectImports,通过该方法再次得到需要加载到IOC容器的相关新的候选类
- String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
- Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
- // 递归调用分析新的候选类是否为ImportSelector类型 or 普通的配置类
- processImports(configClass, currentSourceClass, importSourceClasses, false);
- }
- // 候选类 是接口ImportBeanDefinitionRegistrar的子类
- }else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
- Class<?> candidateClass = candidate.loadClass();
- ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
- ParserStrategyUtils.invokeAwareMethods(egistrar, this.environment, this.resourceLoader, this.registry);
- // 候选类添加到 当前配置类configClass其importBeanDefinitionRegistrars属性中
- configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
- }else {
- // 候选类 是普通的配置类
- String className = candidate.getMetadata().getClassName();
- this.importStack.registerImport(currentSourceClass.getMetadata(), className);
- processConfigurationClass(candidate.asConfigClass(configClass));
- }
- }
- }
- }
DeferredImportSelectorHandler:延迟加载接口ImportSelector导入候选类的handler。通过spi机制加载spring.factories文件下的目标候选类。
延迟是提现在何处呢?
- protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
- throws IOException {
- ...
- Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
- for (MethodMetadata methodMetadata : beanMethods) {
- configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
- }
- ...
- }
获取当前ConfigurationClass类通过@Bean注解注入的实例集合。
为啥多此一举需要把候选类封装为SourceClass?
因为在SpringBoot中候选类的加载分为两部分:JVM & ASM。
- private class SourceClass implements Ordered {
-
- public SourceClass(Object source) {
- this.source = source;
- if (source instanceof Class) {//内省类处理
- this.metadata = AnnotationMetadata.introspect((Class<?>) source);
- }
- else {
- this.metadata = ((MetadataReader) source).getAnnotationMetadata();
- }
- }
-
- public ConfigurationClass asConfigClass(ConfigurationClass importedBy) {
- if (this.source instanceof Class) {
- return new ConfigurationClass((Class<?>) this.source, importedBy);
- }
- return new ConfigurationClass((MetadataReader) this.source, importedBy);
- }
- ...
- }
importedBy:表示当前的sourceClass是被importedBy的@import引入的。
- class ConfigurationClassBeanDefinitionReader {
-
- public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
- TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
- // 集合configurationModel元素为全量bean的类信息
- for (ConfigurationClass configClass : configurationModel) {
- loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
- }
- }
-
- private void loadBeanDefinitionsForConfigurationClass(
- ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
-
- ...
- //当前配置类是通过注解@Import导入则注册配置类其BeanDefinition至bean 工厂中
- if (configClass.isImported()) {
- registerBeanDefinitionForImportedConfigurationClass(configClass);
- }
- // 将配置类中通过注解@Bean注入的bean,其BeanDefinition注册至bean 工厂中
- for (BeanMethod beanMethod : configClass.getBeanMethods()) {
- loadBeanDefinitionsForBeanMethod(beanMethod);
- }
- loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
- // 如果配置类是 接口ImportBeanDefinitionRegistrars 的子类则将该候选类的BeanDefinition注册至bean 工厂中
- loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。