SpringBoot开启自动配置理解

SpringBoot开启自动配置理解
在了解spring boot如何开启自动配置时,应先了解什么是spring boot?

1.spring boot
spring boot是一个简化了spring中多框架中所需大量繁琐的配置文件,服务于框架,且服务范围是简化配置文件的框架
spring boot特点:配置文件更简单,应用部署更简单(spring boot内置服务器,并装备启动类代码),可快速开启一个web容器进行开发
spring boot核心功能:

  • 1.可独立运行spring项目,以jar包形式独立运行
  • 2.内嵌Servlet容器:spring boot可选择内嵌tomcat,jetty或undertow,无序以war包形式部署项目
  • 3.简化maven配置:spring提供推荐基础pom文件来简化maven配置
  • 4.自动配置spring:spring boot会根据项目依赖来自动配置spring框架,极大减少了项目需要使用的配置
  • 5.提供生产就绪性功能:提供可以直接在生产环境中使用的功能,如性能指标,应用信息和应用健康检查
  • 6.无代码生成和xml自动配置:spring boot不生成代码,不需要任何xml配置即可实现spring所有配置
    1
    2
    3
    4
    5
    6
    2.spring boot开启自动配置
    由spring boot原理可知,运行项目需要的tomcat等都被spring boot集成,且简化了maven配置,并不需要xml文件进行配置。而spring项目中,xml文件 用来进行配置是必不可少的,因此,spring boot虽然看不到xml文件,实际上是内部底层进行了处理,原理上仍然是利用了xml文件的作用。

下面就来看看spring boot是如何实现自动配置的吧~

2.1@SpringBootApplication注解
首先看看具体应用及源码:
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
1
2
3
4
5
6
由以上代码可知,App作为一个项目的启动(入口)类,此方法其实是spring boot启动的一种常用方式,即直接使用main方法运行。而,main方法中使用SpringApplication.run()来启动整个应用。需要注意的是:这个启动类使用@SpringBootApplication注解声明,而此注解是SpringBoot的核心注解。

@SpringBootApplication作用:标注这是一个spring boot应用,而被标注的类则是项目的主程序
@SpringBootApplication实现源码:
@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 {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};

@AliasFor(
    annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};

@AliasFor(
    annotation = ComponentScan.class,
    attribute = "basePackages"
)
String[] scanBasePackages() default {};

@AliasFor(
    annotation = ComponentScan.class,
    attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};

@AliasFor(
    annotation = Configuration.class
)
boolean proxyBeanMethods() default true;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
由源码可知,@SpringBootApplication是一个组合注解,其中主要的注解是:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
1
2
3
2.2 @SpringBootConfinuration:标识启动器是一个核心配置类,源码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}

1
2
3
4
5
6
7
8
9
10
11
可以看到此注解中包含了@Configuration注解,使用了此注解的类均为配置类,可配合@Bean(注册bean)使用。因此,@SpringBootApplication注解标识的类也是配置类

2.3 @ComponentScan:定义包扫描规则(配置需要扫描的包)
最重要的是@EnableAutoConfiguration注解

2.4 @EnableAutoConfiguration作用:开启自动配置,自动根据类型扫描此类的所有包,配合@ComponentScan,将主配置类所在包及其下所有子包进行扫描。
@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 {};

}
1
2
3
4
5
6
7
8
9
10
11
12
13
由源码可知:@EnableAutoConfiguration 中组和了@AutoConfigurationPackage注解和@Import({AutoConfigurationImportSelector.class})注解
@AutoConfigurationPackage:定义了spring boot自动导入组件需要遵循的规则,其源码:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}
1
2
3
4
5
6
7
由源码可知,其中重要的注解为:@Import({Registrar.class}),其中,Registrar源码
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}

public Set<Object> determineImports(AnnotationMetadata metadata) {
    return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
}

}
1
2
3
4
5
6
7
8
9
10
11
12
由此可看出,SpringBoot通过使用ImportBeanDefinitionRegistrar来实现Bean的动态注入
@Import({AutoConfigurationImportSelector.class}):此注解是真正开启自动导入配置的,源码如下:
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
1
2
3
4
5
6
7
8
9
其中,通过 selectImports() 方法完成自动配置的导入
在此方法中 由this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata) 执行自动配置操作
getAutoConfigurationEntry()源码:
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
从此方法中可以看出,真正做操作的是List configurations = this.getCandidateConfigurations(annotationMetadata, attributes)
protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, “No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.”);
return configurations;
}
1
2
3
4
5
从此方法源码中可知:使用SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()),(auto configuration classes found in META-INF/spring.factories.)进行配置的加载。
如下图:
在这里插入图片描述
小结
SpringBoot开启自动配置图示简介:
在这里插入图片描述
简单来说,
SpringBoot是通过核心注解@SpringBootApplication,标识启动器。
而@SpringBootApplication内部则是通过@SpringBootConfiguration注解将启动器作为一个配置类。
然后,使用@ComponentScan注解定义包扫描规则,扫描相关注解 扫描范围 当前入口类所在的包 及 子包 (Spring组件扫描)。
再通过@EnableAutoConfiguration注解开启自动配置,初始化spring环境 springmvc环境 ,该注解只能扫描当前类,因此需要配合@ComponentScan使用
@EnableAutoConfiguration注解则是通过@AutoConfigurationPackage注解定义了spring boot自动导入组件,而该注解则通过@Import({Registrar.class})中的Registrar实现了动态注入Bean
@EnableAutoConfiguration注解又通过@Import({AutoConfigurationImportSelector.class})注解真正开启自动导入配置
而@Import({AutoConfigurationImportSelector.class})通过selectImports() 方法完成自动配置的导入
此方法则通过this.getAutoConfigurationEntry() 执行自动配置操作
此方法中则是通过 List configurations = this.getCandidateConfigurations(annotationMetadata, attributes) 真正进行自动配置操作
而 getCandidateConfigurations() 则是通过 SpringFactoriesLoader.loadFactoryNames() 完成配置的加载。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值