本文已参与「新人创作礼」活动,一起开启编程创作之路。
自动配置:根据我们添加的jar包依赖,会自动将一些配置类的bean注册进ioc容器,我们可以需要的地 方使用@autowired或者@resource等注解来使用它。
SpringBoot自动配置原理如何呢,下面是我的简单理解
SpringBoot应用的启动入口是@SpringBootApplication注解标注类中的main()方法,@SpringBootApplication标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main() 方法启动SpringBoot 应用。
@SpringBootApplication
下面是针对SpringBootApplication内部源码进行的分析
@Target({ElementType.TYPE}) //注解的适用范围,Type表示注解可以描述在类、接口、注解或枚举中
@Retention(RetentionPolicy.RUNTIME) //表示注解的生命周期,Runtime运行时
@Documented //表示注解可以记录在javadoc中
@Inherited //表示可以被子类继承该注解
@SpringBootConfiguration // 标明该类为配置类
@EnableAutoConfiguration // 启动自动配置功能
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes =
TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes =AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// 根据class来排除特定的类,使其不能加入spring容器,传入参数value类型是class类型。
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
// 根据classname 来排除特定的类,使其不能加入spring容器,传入参数value类型是class的全
类名字符串数组。
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
// 指定扫描包,参数是包名的字符串数组。
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
// 扫描特定的包,参数类似是Class类型数组。
@AliasFor(annotation = ComponentScan.class, attribute ="basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
,@SpringBootApplication注解是一个组合注解,前面 4 个是注解的元数据信息, 主要看后面3个注解:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个核心注解
1.@SpringBootConfiguration
@SpringBootConfiguration:SpringBoot 的配置类,标注在某个类上,表示这是一个SpringBoot的配置类。
核心源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration // 配置类的作用等同于配置文件,配置类也是容器中的一个对象
public @interface SpringBootConfiguration {
}
@SpringBootConfiguration注解内部有一个核心注解@Configuration,该注解是Spring框架提供的,表示当前类为一个配置类(XML配置文件的注解表现形式),并可以被组件扫描器扫描。由此可见,@SpringBootConfiguration注解的作用与@Configuration注解相同,都是标识一个可以被组件扫描器扫描的配置类,只不过@SpringBootConfiguration是被Spring Boot进行了重新封装命名而已
2.@EnableAutoConfiguration
package org.springframework.boot.autoconfigure;
// 自动配置包
@AutoConfigurationPackage
// Spring的底层注解@Import,给容器中导入一个组件;
// 导入的组件是AutoConfigurationPackages.Registrar.class
@Import(AutoConfigurationImportSelector.class)
// 告诉SpringBoot开启自动配置功能,这样自动配置才能生效。
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
// 返回不会被导入到 Spring 容器中的类
Class<?>[] exclude() default {};
// 返回不会被导入到 Spring 容器中的类名
String[] excludeName() default {};
}
package org.springframework.boot.autoconfigure;
// 自动配置包
@AutoConfigurationPackage
// Spring的底层注解@Import,给容器中导入一个组件;
// 导入的组件是AutoConfigurationPackages.Registrar.class
@Import(AutoConfigurationImportSelector.class)
// 告诉SpringBoot开启自动配置功能,这样自动配置才能生效。
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
// 返回不会被导入到 Spring 容器中的类
Class<?>[] exclude() default {};
// 返回不会被导入到 Spring 容器中的类名
String[] excludeName() default {};
}
Spring 中有很多以Enable 开头的注解,其作用就是借助@Import 来收集并注册特定场景相关的Bean ,并加载到IOC 容器。 @EnableAutoConfiguration就是借助@Import来收集所有符合自动配置条件的bean定义,并加载到IoC容器。
2.1 @AutoConfigurationPackage
@AutoConfigurationPackage:自动配置包,它也是一个组合注解,其中最重要的注解是@Import,@Import是Spring 框架的底层注解,它的作用就是给容器中导入某个组件。比如@Import(AutoConfigurationPackages.Registrar.class) ,它就是将Registrar 这个组件类导入到容器中
AutoConfigurationPackages.Registrar这个类就干一个事,注册一个Bean ,这个Bean 就是 org.springframework.boot.autoconfigure.AutoConfigurationPackages.BasePackages ,它有 一个参数,这个参数是使用了@AutoConfigurationPackage 这个注解的类所在的包路径,保存自动配置 类以供之后的使用。
2.2@Import({AutoConfigurationImportSelector.class})
@Import({AutoConfigurationImportSelector.class})将AutoConfigurationImportSelector 这个类导入到Spring 容器中,AutoConfigurationImportSelector 可以帮助Springboot 应用将所有符合条件的@Configuration配置都加载到当前SpringBoot 创建并使用的IOC 容器( ApplicationContext )中
3. @ComponentScan注解
主要是从定义的扫描路径中,找出标识了需要装配的类自动装配到spring 的bean容器中。
常用属性如下:
- basePackages、value:指定扫描路径,如果为空则以@ComponentScan注解的类所在的包为基本的扫描路径
- basePackageClasses:指定具体扫描的类
- includeFilters:指定满足Filter条件的类
- excludeFilters:指定排除Filter条件的类 当前@ComponentScan注解没有标注basePackages及value,所以扫描路径默认为@ComponentScan 注解的类所在的包为基本的扫描路径(也就是标注了@SpringBootApplication注解的项目启动类所在 的路径)