1、配置绑定(要么使用把它加到容器中,要么在配置类中开启配置绑定)
过程:properties-->配置文件-->JavaBean
~使用原生代码编写(麻烦):
public class getProperties { public static void main(String[] args) throws FileNotFoundException, IOException { Properties pps = new Properties(); pps.load(new FileInputStream("a.properties")); Enumeration enum1 = pps.propertyNames();//得到配置文件的名字 //遍历配置属性名,拿到属性值 while(enum1.hasMoreElements()) { String strKey = (String) enum1.nextElement(); String strValue = pps.getProperty(strKey); System.out.println(strKey + "=" + strValue); //封装到JavaBean。 } } }
~使用注解的方式:@ConfigurationProperties(简单)
(配置文件时yml后缀,所以配置项要用:冒号分隔)
使用@ConfigurationProperties这个注解,说明这是一个配置绑定,且把用@Component加到容器中。
让Car类属性中的值跟配置文件中设置的值已经成功绑定上,也就是配置文件为Car组件的属性赋值。
//测试配置绑定功能
//上一步中,配置文件为Car组件赋值,IOC容器中已经存在该组件,
//我们只要在控制类中使用自动注入,就可以把容器中的组件拿来用
需要修改组件中属性的值,只需要修改配置文件,然后重新启动项目,重新浏览器请求:
~还可以使用@EnableConfigurationProperties + @ConfigurationProperties方式配置
这种方式不需要使用@Component标注配置注解,而是在配置类MyConfig上方加一个注解,来开启某个类的配置绑定和将该类组件自动注册到容器中
2、自动配置原理
2.1引导加载自动配置类 核心注解:@SpringBootApplication,它包含了三个注解:
重点讲解@EnableAutoConfiguration开启自动配置,它又是@AutoConfigurationPackage和@Import这两个注解的合成:
这里用到Import用于给容器中导入一个组件,导的是Registrar这个组件,但是这个组件要干的事是导入一系列组件(MainApplication所在包下)。
底层源代码:Registrar批量注册,根据注解元信息获取MainApplication所在位置、获取所有包名,给容器中导入一系列组件。
~调试代码,查看元信息包含了哪些?
上面的调试看到的是这个注解的元信息!
~计算代码
得到的是包名。
2、@Import({AutoConfigurationImportSelector.class})
1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件 2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类 3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件 4、从META-INF/spring.factories位置来加载一个文件。 默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件 spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
Selector核心代码 this.getAutoConfigurationEntry
public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } }
3、按需加载,只有导进来了某些场景,对应的包才能导入,包下的组件才能生效
~修改默认配置:防止有些用户配置的文件上传解析器不符合规范
@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; } 给容器中加入了文件上传解析器;
XXXAutoConfig自动导进来,给容器装配好一系列组件,这些组件就从xxxProperties中拿值,最终会到配置文件中拿值。
要修改配置文件:方法一查文档、方法二查底层。
4、官方文档:https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/using-spring-boot.html#using-boot
5、最佳实践
5.1 引入场景依赖
https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/using-spring-boot.html#using-boot-starter
5.2查看自动配置了哪些(涉及底层原理,选做)
~自己分析,引入场景对应的自动配置一般都生效了
~配置文件中debug=true开启自动配置报告。Negative(不生效)Positive(生效)
5.3是否需要修改
~参照文档修改配置项:https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-application-properties.html#common-application-properties;自己分析:xxxProperties绑定了配置文件的哪些
~自定义加入或者替换组件(除了改配置外还想增加一些功能):@Bean、@Component。。
~自定义器 XXXCustomizer
~。。。。