前面第一章的内容基本上都是基于注解的Spring内容,想要学好SpringBoot这些Spring基础必不可少。从这章开始就是SpringBoot了,首先学习一下SpringBoot最重要的自动装配原理。
一句话概括SpringBoot的自动配置原理就是:启动时加载所有,最终按照条件进行装配。
本小节重点注解结构列图如下:
@SpringBootApplication:主程序注解;
@SpringBootConfiguration
:表名核心配置类;
@ComponentScan
:开启包扫描;@EnableAutoConfiguration
:启用自动配置;
注:在说明注解时,第一点加粗为注解中文含义,第二点为一般加在哪身上,缩进或代码块为示例,如:
@注解
语句示例
//代码示例
在理解自动装配原理之前,还需要知道配置绑定相关注解。
引入配置文件常用@ImportResource
注解:
@ImportResource("classpath:beans.xml")
引入beans.xml配置文件。配置绑定的核心注解为@ConfigurationProperties
,指读取properties文件中的内容,封装进JavaBean中,以供随时使用。
配置绑定有两种形式:
EnableConfigurationProperties:启用配置属性;
在POJO类上写@ConfigurationProperties
,在配置类上写@EnableConfigurationProperties
;
@EnableConfigurationProperties
的两个核心功能:将按照制定规则与配置文件绑定、将组件导入容器中;
//配置类
@EnableConfigurationProperties(Car.class)
public class MyConfig {
}
//POJO类
@ConfigurationProperties(prefix = "mycar")
public class Car {
private String brand;
private Integer price;
}
#配置文件
mycar:
brand: 小鹏
price: 100000
Component:组件注入;
在POJO类上同时标注这两个注解;
@Component
表示将POJO类作为组件注册进容器中,只有在容器中的组件, 才会拥有SpringBoot提供的强大功能;
@Component
@ConfigurationProperties(prefix = "mycar") //prefix表示前缀
public class Car {
private String brand;
private Integer price;
}
#配置文件
mycar:
brand: 小鹏
price: 100000
SpringBoot自动配置的核心注解是@SpringBootApplication,这是个十分【重要】的注解。
@SpringBootConfiguration
、@EnableAutoConfiguration
、@ComponentScan
);
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{
……
}
建议在下面学习底层注解时对照结构图。
@SpringBootApplication:主程序注解;
@SpringBootConfiguration
:表名核心配置类;
@ComponentScan
:开启包扫描;@EnableAutoConfiguration
:启用自动配置;
下面将对@SpringBootConfiguration
、@EnableAutoConfiguration
、@ComponentScan
三个注解逐一分析。
这三个注解中,@EnableAutoConfiguration为核心。
@Configuration
,代表当前类是一个配置类。在这里指核心配置类。开启包扫描;
标注类上;
可以指定扫描路径,扫描到的包里的注解才能生效。在这里自定义了两个扫描器。
@ComponentScan(basePackages = {"com.dlhjw"})
@SpringBootApplication
的核心功能,其本身也是一个合成注解。
@AutoConfigurationPackage
与@Import
合成:@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
……
}
第一个注解:
MainApplication
所在包下的所有组件用Registrar
方法批量注册进容器里。
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {
……
}
源码级分析:
解释SpringBoot默认的扫描路径为主程序类
MainApplication
所在包及以下:
Registrar方法源码如下:
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
//Registrar方法传递两个参数,第一个是注解的源信息AnnotationMetadata,这个注解标在主程序类MainApplication上(合成注解层层传递)
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//Registrar方法利用注解源信息获取到主程序MainApplication所在包名com.dlhjw.boot,封装成数组,注册进容器里。
AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
}
}
@AutoConfigurationPackage
注解的含义是:将指定的一个包下的所有组件导入进容器。第二个注解
@Conditional
,按需配置;源码级分析:
总体上:利用Selector机制给容器批量导入自动配置类;(底层 -> 实现)
META-INF/spring.factories
位置加载一个文件。即默认扫描当前系统里面所有META-INF/spring.factories
位置的文件。其中最重要的是spring-boot-autoconfigure-2.3.4.RELEASE.jar包里的META-INF/spring.factories(SpringBoot兼容全场景的127个自动配置类就在这里,即xxxxAutoConfiguration
);loadSpringFactories
得到所有的组件;getCandidateConfigurations()
获取到所有需要导入到容器中的配置类(默认导入导容器中的127个全类名组件)getAutoConfigurationEntry(annotationMetadata)
方法获取自动配置集合selectImports(AnnotationMetadata am)
方法,返回String数组,数组里说明了需要导入的自动配置类(组件)。虽然127个场景的所有自动配置启动的时候默认全部加载。
xxxxAutoConfiguration
但我们不一定全部都会用到,需要按照条件装配规则@Conditional
,按需配置。
例:给容器中加入文件上传解析器;
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
return resolver;
}
约定大于配置思想: SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
@ConditionalOnMissingBean
注解,表示当容器中没有该组件时,才会注册SpringBoot默认的。//源码里
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
}
用户配置方式(定制化配置):
定制化配置基于属性绑定注解
@EnableConfigurationProperties
与修改默认配置方法
在config包下的配置文件类上标注引入配置文件注解@ImportResource
@ImportResource("classpath:beans.xml")
public class MyConfig(){
//(*)
}
在config包下的配置文件类里(*)处配置用户方式
@Bean
public CharacterEncodingFilter myFilter() {
……
}
在 application.properties
配置文件里配置(推荐)
@EnableConfigurationProperties
注解,找到对应的xxxProperties
类。SpringBoot默认扫描主程序所在包及其下面的所有子包里面的组件,但可以改变扫描路径。
改变扫描路径:
排除自动扫描:
@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)
取消数据库配置。一句话概括SpringBoot的自动配置原理就是:启动时加载所有,最终按照条件进行装配。
即:
xxxxxAutoConfiguration
;xxxxProperties
里面取,xxxProperties
和配置文件进行了绑定;@EnableConfigurationProperties
与修改默认配置方法
@Bean
替换底层的组件(基于SpringBoot的@ConditionalOnMissingBean);主程序注解结构列图
这里再列一下结构图,因为本小节的精髓都在这了。
@SpringBootApplication:主程序注解;
@SpringBootConfiguration
:表名核心配置类;
@ComponentScan
:开启包扫描;@EnableAutoConfiguration
:启用自动配置;
其他说明:
SpringBoot | 2.1 SpringBoot自动装配原理
原文:https://www.cnblogs.com/dlhjw/p/15027761.html