在学习SpringBoot时,遇到@EnableWebMvc注解:
(1)EnableWebMvc的核心,引入了DelegatingWebMvcConfiguration实例;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
(2)而 DelegatingWebMvcConfiguration 继承 WebMvcConfigurationSupport
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
(3)在SpringBoot的WebMvc自动配置类中 WebMvcAutoConfiguration ,有注解 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class),即当 WebMvcConfigurationSupport 存在时,WebMvcAutoConfiguration不生效
@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 {
产生疑问:
@EnableWebMvc 注解引入的是 DelegatingWebMvcConfiguration 实例,
而 @ConditionalOnMissingBean 参数是 WebMvcConfigurationSupport 类(DelegatingWebMvcConfiguration 的父类),
猜想:
是否即 @ConditionalOnMissingBean 会识别到 WebMvcConfigurationSupport 的继承树,容器中存在 WebMvcConfigurationSupport 的子类,@ConditionalOnMissingBean 也返回 false,使得该自动配置类也不生效?
进行验证:
@SpringBootTest
public class ConditionalOnMissingBeanTests {
//获取notebookPC实例
@Qualifier("notebookPC")
@Autowired(required = false)
Computer notebookPC;
//获取reservePC实例
@Qualifier("reservePC")
@Autowired(required = false)
Computer reservePC;
//获取laptop实例
@Autowired(required = false)
Laptop laptop;
//获取phone实例
@Autowired(required = false)
Phone phone;
//获取singlePhone实例
@Autowired(required = false)
SinglePhone singlePhone;
//测试方法体,容器中是否有这些对象
@Test
void contextLoads() {
System.out.println("reservePC:" + notebookPC);
System.out.println("reservePC:" + reservePC);
System.out.println("laptop:" + laptop);
System.out.println("phone:" + laptop);
System.out.println("singlePhone:" + singlePhone);
}
}
//配置类
@Configuration
class BeanConfig {
//注入notebookPC实例
@Bean(name = "notebookPC")
public Computer computer1(){
return new Computer("笔记本电脑");
}
//当容器中没有Computer类时,注入reservePC实例
@ConditionalOnMissingBean(Computer.class)
@Bean("reservePC")
public Computer computer2(){
return new Computer("备用电脑");
}
//关键:测试只注入Computer类实例,未注入Tools类实例,@ConditionalOnMissingBean条件是否会向上检索到父类,即@ConditionalOnMissingBean条件是否是父类下的所有类型存在都生效,向下检索
//当容器中没有Tools类时,注入laptop实例。Computer继承Tools类
@ConditionalOnMissingBean(Tools.class)
@Bean("laptop")
public Laptop laptop(){
return new Laptop("笔记本");
}
//拓展:验证是否向上检索
//当容器中没有Phone类时,才注入。Phone类继承Conputer类
@ConditionalOnMissingBean(Phone.class)
@Bean("phone")
public Phone phone(){
return new Phone("手机");
}
//当容器中没有singlePhone类时,才注入。
@ConditionalOnMissingBean(SinglePhone.class)
@Bean("singlePhone")
public SinglePhone singlePhone(){
return new SinglePhone("Single手机");
}
}
//Tools类
class Tools{
private String name;
public Tools() {
this.name = name;
}
}
//关键:Computer类,继承Tools类
class Computer extends Tools{
private String name;
public Computer(String name) {
this.name = name;
}
}
//Laptop类
class Laptop{
private String name;
public Laptop(String name) {
this.name = name;
}
}
//拓展:Phone类,继承Conputer类
class Phone extends Computer{
private String name;
public Phone() {
}
public Phone(String name) {
this.name = name;
}
}
//SinglePhone类
class SinglePhone{
private String name;
public SinglePhone() {
}
public SinglePhone(String name) {
this.name = name;
}
}
运行结果:
结论:
@ConditionalOnMissingBean 会识别到 参数中的类 的继承树,当容器中存在 该类 或 该类的子类 或 该类的父类 的类型时,@ConditionalOnMissingBean 返回false ,使得 @ConditionalOnMissingBean 标注的类 不执行。
具体原理,还没找到,所以用简陋的方式进行验证。如果读者了解,请赐教。