@SpringBootApplication注解
点击这个注解
里面有这样3个注解
@SpringBootConfiguration(重要)
@EnableAutoConfiguration(重要)
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
其中@ComponentScan是组件扫描器注解,他会自动扫描并加载符合条件的组件或Bean,并将这个Bean加载到IoC容器中,这个注解对应Spring中xml配置文件中的元素,有了它就会有相应的Bean,和spring的xml文件中添加Bean一样。
而@SpringBootConfigration这个注解则表明这个类是一个SpringBoot配置类,点击这个注解,发现其下有一个 @Configration 说明这是一个Spring配置类,配置类就对应Spring中的xml配置文件,在配置类中可以进行相应的配置,和在spring的xml文件中进行相应的配置一样 @Configration下有一个@Component注解,表明配置类就是一个Spring中的组件,这里也说明启动类也只是Spring中的一个组件罢了,用来启动应用
从这个注解的名字我们就知道他与自动配置有关
他会告诉SpringBoot开启自动配置功能,这样自动配置才会生效
其下有两个重要注解
@AutoConfigrationPackage
@Import(AutoConfigrationImportSelector.class)
@AutoConfigrationPackage,点进去,有一个@Import(AutoConfigrationPackage.Registrar.class),@Import是Spring的底层注解,给IoC容器导入一个组件,Registrar.class的作用是将主启动类的所在包及其所有子包里面的所有组件扫描到Spring容器中,这也是我们的包为什么要和启动类同级的原因。这个注解就将我们自己写的所有组件扫描到了Spring容器中。
@Import(AutoConfigurationImportSelector.class),给容器导入组件,这里的组件就是那些我们原本需要配置的组件了。AutoConfigurationImportSelector类中有一个getCondidateConfigrations(),这个方法用于获取所有候选的配置
这个方法又调用了SpringFactoriesLoader的静态方法loadFactoryNames,loadFactoryNames方法的一个参数是getSpringFactoriesLoaderFactoryClass()方法,这个方法是
可以看到它返回的是EnableAutoConfiguration.class,也就是说这个方法返回的是标注了这个注解的所有包,而启动类就被这个注解标注,在loadSpringFactories方法中启动类又被返回。所以说他做这一圈操作,就是为了将启动类所需的所有资源导入。
现在回到loadFactoryNames方法,loadFactoryNames方法调用了SpringFactoriesLoader类中的静态方法loadSpringFactories,loadSpringFactories方法又调用了spring.factoires文件
这个文件中有很多自动配置的文件,他们的命名形式为xxxxAutoConfigration,我们熟悉的WebMvcAutoConfiguration,HttpEncodingAutoConfiguration等等都在其中。
以HttpEncodingAutoConfiguration为例:
//表明这是一个配置类,和以前的配置类一样,可以向容器中添加组件
@Configuration(proxyBeanMethods = false)
//与ServerProperties类绑定,从这个类中获取对应的属性
@EnableConfigurationProperties(ServerProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
private final Encoding properties;
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
...
}
...
}}}
它对应的properties为ServerProperties.java,当HttpEncodingAutoConfiguration中的组件生效时,组件会从ServerProperties类中获取相应的属性
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {...}
这个类和我们的配置文件绑定,其中有一些属性,prefix就是我们配置时需要使用的前缀,使用这个前缀我们就可以在我们的配置文件中进行相应的配置了,例如:server.port=8080
所以自动配置的大概过程就是
当@ConditionOnxxxx()条件不成立的时候,该自动配置类就不会生效。在通过spring.factories获取配置类位置之后就不会加载这个自动配置类,如果条件成立,就加载这个自动配置类到Ioc容器中,这样自动配置类就生效了,我们就不需要再配置了。一旦这个自动配置类生效,就会向容器中添加各种组件,这些组件的属性是从对应的properties类中获取的(通过@EnableConfigurationProperties(xxxxProperties.class)绑定)。
自定义一个类,用@ConfigurationProperties(prefix="")和@Component来修饰它
例如:
@Component
@ConfigurationProperties(prefix="hhh")
public class hhhconfig(){
private String hhhName;
private int age;
对应的set,get方法
}
在我们的yml文件中添加
hhh
hhhname:testhhh
age:3333
@SpringBootTest
class SpringbootdemoApplicationTests {
@Autowired
TestConfig hhhconfig;
@Test
void contextLoads() {
System.out.println(hhhconfig.getHhhName());
System.out.println(hhhconfig.getAge());
}
}
会输出我们配置的结果,所以想要配置自动配置类中不存在的属性,就自己写一个properties类就可以了。
感觉写博客确实对理解知识很有帮助,当你能讲一个知识点讲出来的时候说明你已经理解得很透彻了,花1个小时写博客确实比自己看1个小时知识点理解的更快。
从今天起要多写博客。
顺便吐槽下,CSDN这个编辑器是真的烂。