SpringBoot启动过程(3)@SpringBootApplication注解

大家都知道springboot 在入口类会有个注解叫@SpringBootApplication注解,这其实是个组合的注解类spring boot通过此注解实现了自动装配:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//使用自定义注解时,如果注解在类上面子类会自动继承此注解。
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
//扫描注解
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    ...
    ...
}

1、@SpringBootConfiguration

@SpringBootConfiguration这个注解其实很大程度上只是为了标注这个类是一个配置类。
其核心就在于继承了@Configuration注解, @Configuration 注解的类会将其中 @Bean 注解的方法所生成并返回的对象交由 Spring 容器来进行管理。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

1.1、@Configuration

@Configuration注解主要是通过ConfigurationClassPostProcessor类实现其主要的业务逻辑:

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        int registryId = System.identityHashCode(registry);
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        } else if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
        } else {
            this.registriesPostProcessed.add(registryId);
            this.processConfigBeanDefinitions(registry);
        }
}
 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList();
        String[] candidateNames = registry.getBeanDefinitionNames();
        String[] var4 = candidateNames;
        int var5 = candidateNames.length;
        // 先获取所有configuration classes自身的bean definitions
        for(int var6 = 0; var6 < var5; ++var6) {
            String beanName = var4[var6];
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            //判断configurationClassAttrbute属性是否存在,如果存在证明已经处理过了
            if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            } 
            //判断是否是configuration类
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
        if (!configCandidates.isEmpty()) {
        // 预处理configuration的bean definitions
            configCandidates.sort((bd1, bd2) -> {
                int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                return Integer.compare(i1, i2);
            });
            SingletonBeanRegistry sbr = null;
            //单例bean的注册
            if (registry instanceof SingletonBeanRegistry) {
                sbr = (SingletonBeanRegistry)registry;
                if (!this.localBeanNameGeneratorSet) {
                    BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
                    if (generator != null) {
                        this.componentScanBeanNameGenerator = generator;
                        this.importBeanNameGenerator = generator;
                    }
                }
            }
            if (this.environment == null) {
                this.environment = new StandardEnvironment();
            }
        //通过ConfigurationClassParser解析所有configuration class的bean definitions
        //统一封装成ConfigurationClass对象,包含所有支持元素:
        // @Bean @Import @ImportResource @ComponentScans @PropertySource @PropertySources等
            ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
            Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
            HashSet alreadyParsed = new HashSet(configCandidates.size());
            do {
                StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
                //解析配置类
                parser.parse(candidates);
                parser.validate();
                //前面解析配置类,只有 @Configuration 和通过 @ComponentScan 注解扫描出来的类才会加入到 BeanFactory 的 BeanDefinitionMap
                // 其他注解,例如@Import、@Bean,会包装为 ConfigurationClass 类
                Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
                configClasses.removeAll(alreadyParsed);
                //将ConfigurationClass对象解析为对应的bean definitions
                if (this.reader == null) {
                    this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
                }
                this.reader.loadBeanDefinitions(configClasses);
                alreadyParsed.addAll(configClasses);
                processConfig.tag("classCount", () -> {
                    return String.valueOf(configClasses.size());
                }).end();
                candidates.clear();
                if (registry.getBeanDefinitionCount() > candidateNames.length) {
                    //记录下最新的配置类
                    String[] newCandidateNames = registry.getBeanDefinitionNames();
                    Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
                    Set<String> alreadyParsedClasses = new HashSet();
                    Iterator var13 = alreadyParsed.iterator();
                    while(var13.hasNext()) {
                        ConfigurationClass configurationClass = (ConfigurationClass)var13.next();
                        alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                    }
                    String[] var24 = newCandidateNames;
                    int var25 = newCandidateNames.length;
                    for(int var15 = 0; var15 < var25; ++var15) {
                        String candidateName = var24[var15];
                        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());
            if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
                sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
            }
            if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
                ((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();
            }
        }
    }

看了以上代码可以了解到能被当做配置类的,不仅仅是@Configuration,还有@Bean,@Component,@ComponentScan,@Import,@ImportResource这些注解 Spring 认为也是配置类。不同的是 @Configuration 注解标记为FULL模式,而其他标记为LITE模式。
可以了解到通过增加@Configuration注解可以将类转化为BeanDefinition,在ApplicationContext后续的初始化中提供bean的初始化等功能。

2、@EnableAutoConfiguration

org.springframework.boot.autoconfigure.@EnableAutoConfiguration 是用于开启自动配置功能,是 自动配置的最核心的注解。代码如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class<?>[] exclude() default {};
    String[] excludeName() default {};
}

2.1、@AutoConfigurationPackage

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};
    Class<?>[] basePackageClasses() default {};
}

添加该注解的类所在的package 作为自动配置package进行管理,注册对应的bean到ioc容器中。

2.2、AutoConfigurationImportSelector

通过@import方式导入了AutoConfigurationImportSelector选择器,在启动过程中,调用的是其getAutoConfigurationEntry方法

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            //获取配置数组
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            //需要移除重复的配置
            configurations = this.removeDuplicates(configurations);
            //排除属性 -(1)
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            //filter会过滤掉不符合配置的类,具体需要查看Condition
            configurations = this.getConfigurationClassFilter().filter(configurations);
            //自动配置导入的事件 -(2)
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }   
    //(1)
    protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        Set<String> excluded = new LinkedHashSet();
        //获取注解上有关exclude的属性
        excluded.addAll(this.asList(attributes, "exclude"));
        //获取注解上有关excludeName的属性
        excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
        // 配置文件的 spring.autoconfigure.exclude 属性
        excluded.addAll(this.getExcludeAutoConfigurationsProperty());
        return excluded;
    }
    //(2)
    private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
         在META-INF/spring.factories配置中找到AutoConfigurationImportListener的所有监听器。
        List<AutoConfigurationImportListener> listeners = this.getAutoConfigurationImportListeners();
        if (!listeners.isEmpty()) {
            AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
            Iterator var5 = listeners.iterator();
            while(var5.hasNext()) {
                AutoConfigurationImportListener listener = (AutoConfigurationImportListener)var5.next();
                //设置Aware属性 (2.1)
                this.invokeAwareMethods(listener);
                //导入事件通知
                listener.onAutoConfigurationImportEvent(event);
            }
        }
    }
    //(2.1)
    private void invokeAwareMethods(Object instance) {
        if (instance instanceof Aware) {
            if (instance instanceof BeanClassLoaderAware) {
                ((BeanClassLoaderAware)instance).setBeanClassLoader(this.beanClassLoader);
            }
            if (instance instanceof BeanFactoryAware) {
                ((BeanFactoryAware)instance).setBeanFactory(this.beanFactory);
            }
            if (instance instanceof EnvironmentAware) {
                ((EnvironmentAware)instance).setEnvironment(this.environment);
            }
            if (instance instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware)instance).setResourceLoader(this.resourceLoader);
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值