文章目录
自动配置原理入门
1.引导加载自动配置类
自动配置因为是在:主程序类
中添加了@SpringBootApplication
注解
由于@SpringBootApplication
注解是由下面三个注解组成的
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}
A.@SpringBootConfiguration
注解
@SpringBootConfiguration
注解本质就是一个@Configuration
注解,说明:@SpringBootConfiguration
标识的类就是一个配置类
@Configuration
@Indexed
public @interface SpringBootConfiguration {}
B.@ComponentScan
注解
@ComponentScan
是用于包扫描的
C.@EnableAutoConfiguration
注解【重点】
@EnableAutoConfiguration
注解作用是:一个是加载指定包中所有组件,一个是加载系统文件"META-INF/spring.factories"
中的组件【注意是:在"META-INF/spring.factories"
中的组件是按照条件装配规则(@Conditional
)】
@EnableAutoConfiguration
是@SpringBootApplication
注解的组合注解中的其中一个,也是最重要的一个
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
1》@AutoConfigurationPackage
:自动配置包?指定了默认的包规则
@AutoConfigurationPackage
注解说明了指定导入那个包及其子包的所有组件
@Import(AutoConfigurationPackages.Registrar.class)// 给`@Import`注解是导入一个组件
public @interface AutoConfigurationPackage {}
// 利用Registrar给容器中导入一系组件
// 将指定的一个包下的所有组件导入进行:就是`主程序类`所在包下及其子包
Registrar
类:该类是用来注册主程序类
下所在包下及其子包的组件 【就是利用Registrar
给容器创建一系列对象】
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
// new PackageImports(metadata).getPackageNames()是获取当前`主程序类`所有在的包
//register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));是注册`主程序类`所有在包及其子包
}
}
2》@Import(AutoConfigurationImportSelector.class)
@Import(AutoConfigurationImportSelector.class)
是加载默认扫描我们当前系统里面所有META-INF/spring.factories
位置中的文件
1.利用getAutoConfigurationEntry(annotationMetadata);方法给容器中批量导入一些组件
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
2.调用public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {}获取到所有需要导入到容器中的配置类
3.private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);得到所有组件
4.从`META-INF/spring.factories`位置来加载一个文件
默认扫描我们当前系统所有META-INF/spring.factories位置文件
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
总结:@Import(AutoConfigurationImportSelector.class)
是从当前系统的"META-INF/spring.factories"位置扫描需要加载的组件【注意是:在"META-INF/spring.factories"
中的组件是按照条件装配规则(@Conditional
),不是一下子全部加载是按照条件装配规则加载】
2.修改SpringBoot
底层默认配置
例如:
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {
//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。
//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}
给容器中加入了文件上传解析器;
说明了:SpringBoot
默认会在底层配好所有的组件,但是如果用户自己配置了以用户的优先
总结:【非常重要】
SpringBoot
先加载所有的自动配置类xxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定文件指定的值。
xxxProperties
里面拿,xxxProperties
和配置文件进行了绑定 - 生效的配置类就会给容器中装配很多组件【原因是有了这个组件,才能进行指定的装配】
- 根据上面说明:我们可以定制化配置两种方式
- 用户直接自动定义一个配置类使用
@Bean
创建一个Bean对象替换底层的组件【因为底层做了判断用户有自己定义组件,则用用户的】 - 用户去看这个组件是获取的配置文件什么值就去修改核心配置文件即可【开发推荐使用,如下面示例】
- 用户直接自动定义一个配置类使用
**示例一:**有:@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
注解直接从该注解获取前缀
例如:下面SpringMVC
字符编码:解决中文乱码问题
第一步:查看底层config
包中找到指定类
@Configuration(proxyBeanMethods = false) // 这是一个配置类
@EnableConfigurationProperties(ServerProperties.class) // 与ServerProperties.class类,表示开启配置绑定
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) //是否是原生态Servlet
@ConditionalOnClass(CharacterEncodingFilter.class) //在容器中是否有CharacterEncodingFilter组件,有才进行下面自动装配
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true) //是否包含该配置文件:前缀是:`server.servlet.encoding`,如果没有也默认有了
public class HttpEncodingAutoConfiguration {}
第二步:@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
注解【有@ConditionalOnProperty
注解直接从这个注解中获取前缀,没有再找@EnableConfigurationProperties(ServerProperties.class)
中获取前缀】:获取前缀:server.servlet.encoding
第三步:在application.properties
核心配置文件中修改:
#修改字符编码
server.servlet.encoding.charset=GBK
注意是:示例一本质就是示例的方式
示例二:@EnableConfigurationProperties(CacheProperties.class)
中获取前缀
第一步:查看底层源码
@Configuration(proxyBeanMethods = false)表示配置类
@ConditionalOnClass(CacheManager.class)是否包含该CacheManager.class类在容器中
@ConditionalOnBean(CacheAspectSupport.class)是否包含该Bean在容器中CacheAspectSupport.class
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")不包含该Bean在容器中
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureAfter({ CouchbaseDataAutoConfiguration.class, HazelcastAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
@Import({ CacheConfigurationImportSelector.class, CacheManagerEntityManagerFactoryDependsOnPostProcessor.class })
public class CacheAutoConfiguration {}
第二步:@EnableConfigurationProperties(CacheProperties.class)
定位到该注解的CacheProperties
类上
@ConfigurationProperties(prefix = "spring.cache")
public class CacheProperties {}
第三步:获取前缀 :spring.cache
第四步:在核心配置文件application.properties
中修改默认配置
#配置缓冲
spring.cache.ehcache.config=bean.xml
非常重要:xxxAutoConfiguration
—> 组件 ----> xxxProperties
里面拿值 ----> application.properties
,由于组件和核心配置文件application.properties
存在上述关系,我们只需要修改核心配置文件,就是修改掉底层默认的值
3.开发SpringBoot
实践步骤
A.引入场景依赖
参考下面官方地址
[Developing with Spring Boot](https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.build-systems.starters)
B.查看自动配置了哪些是否生效了
方式一:自动分析,引入场景对应的自动配置
方式二:在核心配置文件application.properties
中开启debug=true
自动配置报告
-
Positive
表示是生效的 -
Negative
表示是不生效的
C.是否需要修改配置文件
方式一:和上述修改SpringBoot底层默认配置一样
方式二:参考官方文档:
(https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties)
D.自定义加入或者替换组件
@Bean
和 @Component