1. SpringBoot自动装配
1. 1 @SpringBootApplication
@SpringBootApplication的启动类注解主要包括:
- @SpringBootConfiguration:实质是@Configuration,代表当前是一个配置类
- @EnableAutoConfiguration:自动装配的核心
- @ComponentScan:指定扫描路径,Spring注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{}
1.2 @EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
1.2.1 @AutoConfigurationPackage
自动配置包,指定了默认的包规则。
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
1.2.2 @Import(AutoConfigurationImportSelector.class)
publlic String[] selectImports(){} 返回需要加载的类路径
- 利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
- 调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
- 利用工厂加载 List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());得到所有的组件
- 从META-INF/spring.factories位置来加载一个文件。默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件。spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
- 这个spring.factories文件中包含有127个自动配置类
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\....
6. 按需开启自动配置项。虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration 按照条件装配规则(@Conditional),最终会按需配置。
7. 在自动配置类xxxAutoConfiguration上,会有@EnableConfigurationProperties进行属性值的绑定。
总结:
- SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
- 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定。
- 生效的配置类就会给容器中装配很多组件
- 只要容器中有这些组件,相当于这些功能就有了
- 定制化配置(1. 用户直接自己@Bean替换底层的组件;2. 用户去看这个组件是获取的配置文件什么值就去修改。)
xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties
2. SpringBoot处理表单的PUT、DELETE请求
2.1 form表单的method只能使用get/post
form表单的method只能使用get/post,这样后端SpringBoot的RESTful API方式的put更新或者delete删除方法,就没办法匹配。但SpringMVC在这块有HiddenHttpMethodFilter进行了转换。
WebMvcAutoConfiguration 中 OrderedHiddenHttpMethodFilter 默认是false。
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false) // 不配置默认为false
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
// 继承结构
public class OrderedHiddenHttpMethodFilter extends HiddenHttpMethodFilter implements OrderedFilter {}
// HiddenHttpMethodFilter 中的 doFilterInternal
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
HttpServletRequest requestToUse = request;
// post提交的表单,提取表中隐藏字段“_method”中的方法作为转换对象
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HttpMethodRequestWrapper(request, method);
}
}
}
filterChain.doFilter(requestToUse, response);
}
2.2 转换过程
表单请求Rest原理(表单提交要使用REST的时候,表单只能写get/post方法)
- 表单提交会带上 name=_method, value=PUT, type=hidden
- 请求过来被 HiddenHttpMethodFilter 拦截
- 请求是否正常,并且是POST
- 获取到_method的值。(兼容以下请求;PUT、DELETE、PATCH)
- 原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的_method值。
- 过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。
客户端工具请求Rest
- 如PostMan直接发送Put、delete等方式请求(非表单方式)可以匹配requestMapping