1.什么是SpringBoot?
这里简单说一下,大家都应该都用过SSM,也就是Spring,SpringMVC,Mybatis,那整合这三个就是大家所熟悉的SSM,所以里面会有很多的配置文件,Spring的配置文件----Spring.xml(名字不固定),mybatis的配置文件,SpringMVC的配置文件,相信大家已经配到快奔溃了(我也是这么过来的)。
但是其实说白了SSM就是几个熟悉的层,dao层,mapper层,service层,controller层,SpringBoot就非常好,这个框架会有一个默认的配置文件,applicatio.yml,里面配置基本的端口号,还有你自己的数据库信息,然后就可以了,是的,没有那么多配置文件,多了什么?多了一些依赖包而已,这些包都是以spring-boot-starter开头,你只要在创建SpringBoot框架时勾选添加或者引入即可。
那这些又是嘛嘞?
这个时候就得来讲讲SpringBoot的一个特点,约定大于配置,很多配置内容它帮我们配好了,这种就叫做自动配置。
2.略显粗糙的源码分析
这个是启动类的代码
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
我们ctrl+鼠标点击这个@SpringBootApplication,进去里面的内容
@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({ElementType.TYPE}) :元注解,标注这个注解只能在类上使用 @Retention(RetentionPolicy.RUNTIME):元注解,标注这个注解在运行时解析,它的生命周期是RUNTIME @Documented:元注解,表明这个注解应该被javadoc工具记录 @Inherited:元注解,表明子类会自动继承该注解
我们ctrl+鼠标点击这个@EnableAutoConfiguration,进去里面的内容
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
我们ctrl+鼠标点击这个AutoConfigurationImportSelecto,进去里面的内容
其实我们可以看到一个大概的苗头了,它的提示信息说,没有找到META-INF/spring的class下面找到文件,那看一下怎么判断的,是一个loadFactoryNames()方法,再点进去
这大概的意思就是启动时会去看一下这个spring.factories文件。
看这个文件干嘛呢?
因为自动配置类是SpringBoot规定的加载规则,默认规则为加载每个jar包下的/META-INF/spring.factories
文件中的org.springframework.boot.autoconfigure.EnableAutoConfiguration
指定的自动配置类;
springBoot有两种配置类,一种是普通的配置类,一种是自动配置类。
普通配置类,在类上方标一个注解,@Configu/ration
自动配置类,注解的同时,还要写在/META-INF/spring.factories
中的;
3.写一个自己的排除器
说了那么多,到底要写什么嘞?
我们可以自定义一个排除器,用来过滤某些bean,话不多说,直接上代码
首先,在resources下面建立一个META-INF文件夹,再建立一个spring.factories文件
# Initializers
org.springframework.context.ApplicationContextInitializer=\
com.MyApplicationContextInitializer
这里指定了com包下面的MyApplicationContextInitializer类
package com;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
// 往IOC容器中注册一个单例Bean(在IOC容器初始化后,@ComponentScan组件扫描之前执行)
applicationContext.getBeanFactory().registerSingleton("myTypeExcludeFilter",new MyTypeExcludeFilter());
}
}
看代码,我们还要建立一个MyTypeExcludeFilter的类
import java.io.IOException;
public class MyTypeExcludeFilter extends TypeExcludeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// 排除HelloController
return metadataReader.getClassMetadata().getClassName().equals(HelloController.class.getName());
}
}
这是直接将HelloController里的路径全都排除,也就是说,你现在访问不到这个路径了
这是helloController里的代码
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
@GetMapping("/ok")
public String ok(){
return "ok";
}
}
先不开启排除器,我们先把spring.factories的代码注释掉,测试一下
现在恢复文件的代码,再次启动 ,就会发现它404了