在之前的文章中有提到过SpringBoot自动装配的一个原理 今天来研究以下SpringBoot中WebMVC模块儿是如何实现自动配置的
1.@SpringBootApplication: 首先 这个注解 接触过SpringBoot的学者都知道 用这个注解标注的类是SpringBoot的启动类 当我们按住ctrl+鼠标左键点进去后会发现以下注解代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@Target这个注解中包含了一个枚举类型说明当前这个注解类型为枚举类型
@SpringBootConfiguration这个注解顾名思义为SpringBoot的配置类
@EnableAutoConfiguration: 这个注解是整个SpringBoot自动配置的一个核心 这个注解的意思为 开启自动配置 当我们按住ctrl+鼠标左键点进去这个注解后会发现如下代码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
点进来这个注解我们可以发现@AutoConfigurationPackage这个注解 这是SpringBoot自动配置包的一个实现(本文中不做重点研究对象) 我们可以看到 @Import(AutoConfigurationImportSelector.class) 这个注解 Java学到这里都知道Import是导入的意思 那么这个注解中包含了AutoConfigurationImportSelector.class 这个类就是自动配置选择导入器 当我们再次按住ctrl 点进去这个类时可以发现这样一个方法
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
这个notEmpty是Assert类中的一个方法 再点入这个notEmpty方法看一下具体实现
public static void notEmpty(@Nullable Collection<?> collection, String message) {
if (CollectionUtils.isEmpty(collection)) {
throw new IllegalArgumentException(message);
}
}
在这个方法的实现中我们不难看出 这个方法中包含了两个参数和一个注解@Nullable 这个注解的意思就是可以为null 再看一下这个方法体 如果collection这个参数为null 则会手动抛出一个异常对象 这个异常对象的打印信息就是 这个方法中的字符串
No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.
翻译过来的意思为:在META-INF/spring.factories中找不到自动配置类。如果你如果正在使用自定义打包,请确保文件正确。 那这个自动配置类在哪里找? 因为博主使用的开发工具为IDEA 所以在左侧的External Libraries中可以发现Maven的依赖
在这个Spring.factories文件中我们可以找到WebMvcAutoConfiguration这个类(大约在146行左右)
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
继续ctrl+鼠标左键点进去可以发现如下代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
/**
* The default Spring MVC view prefix.
*/
public static final String DEFAULT_PREFIX = "";
/**
* The default Spring MVC view suffix.
*/
public static final String DEFAULT_SUFFIX = "";
private static final String SERVLET_LOCATION = "/";
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = false)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
@Bean
@ConditionalOnMissingBean(FormContentFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.formcontent.filter", name = "enabled", matchIfMissing = true)
public OrderedFormContentFilter formContentFilter() {
return new OrderedFormContentFilter();
}
// Defined as a nested config to ensure WebMvcConfigurer is not read when not
// on the classpath
@SuppressWarnings("deprecation")
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class,
org.springframework.boot.autoconfigure.web.ResourceProperties.class, WebProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
private final WebMvcProperties mvcProperties;
在这一部分代码块儿中的第二个注解我们可以发现当前类的类型为Servlet 在@ConditionalOnClass这个注解中引入了三个类 Servlet.class DispatcherServlet.class WebMvcConfigurer 这些都是我们S平ringMVC中必不可少的部分 在这个类的代码块儿中 我们可以看到SpringMVC 配置文件中视图解析器配置前后缀以及servlet_location的属性 即这部分代码
public static final String DEFAULT_PREFIX = "";
public static final String DEFAULT_SUFFIX = "";
private static final String SERVLET_LOCATION = "/";
当我们继续在这个类中查看下面的代码时,我们可以发现 这个类中含有一个静态内部类 代码如下
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
private final WebMvcProperties mvcProperties;
在这个静态内部类中 我们可以看到这个属性
private final WebMvcProperties mvcProperties;
当我们继续点入WebMvcProperties 这个类中我们可以发现很多webmvc这个模块儿中所需要的信息都包含在这个类中 这样就完成了它的自动装配
ps: 以上内容仅是个人理解 如有不足 还望补充 大佬们嘴下留情 谢谢~