@SpringBootApplication你知多少?

我们都知道@SpringBootApplication注解是spring boot项目的启动注解。那么它具体表示什么含义呢,或者说都包含什么功能呢?接下来我们一探究竟。

一、解析@SpringBootApplication

SpringBootApplication是一个组合注解

1598407219679

1598407238400

(1)元注解

前四个是专门用于对注解进行注解的,称为元注解。

  • @Target
  • @Retention
  • @Documented
  • @Inherited:表示该注解会被子类自动继承。

(2)@SpringBootConfiguration

查看该注解的源码注解可知,该注解与@Configuration 注解功能相同,仅表示当前类为一个 JavaConfig 类,其就是为 Spring Boot 专门创建的一个注解。 所以,通常你会看到有人在启动类中使用@Bean注解生成一个实例对象。

1598407594516

(3)@ComponentScan

用于完成组件(@Component,@Controller,@Service,@Repository)扫描。不过需要注意,其仅仅用于配置组件扫描指令,并没有真正扫描,更没有装配其中的类,这个真正扫描是由@EnableAutoConfiguration 完成的。

注意一点:Spring Boot1.x 版本中仅会扫描当前标注类所在包的子孙包,不会扫描标注类所在的包。但 Spring Boot2.x 版本中默认会扫描当前注解所标注类所在的包及其子孙包。

(4)@EnableAutoConfiguration

@EnableAutoConfiguration表示开启自动配置功能。@EnableXxx 注解一般用于开启某一项功能,是为了简化代码的导入,即使用了该类注解,就会自动导入某些类。所以该类注解是组合注解,一般都会组合一个@Import 注解,用于导入指定的多个类,而被导入的类一般分为三种:配置类、选择器,与注册器。@import注解中导入的类可以认为是具体的配置功能实现类,也可以理解为是框架内部需要使用的Bean。

1598409693267

举例说明@Import导入类(了解):

A、配置类

@Import 中指定的类一般以 Configruation 结尾,且该类上会注解@Configuration,表示当前类为一个配置类。

1598409847148

1598409886148

B、选择器

@Import 中指定的类一般以 Selector 结尾,且该类实现了 ImportSelector 接口,表示当前类会根据条件选择要导入的类。

1598410003403

C、注册器

@Import 中指定的类一般以 Registrar 结尾,且该类实现了 ImportBeanDefinitionRegistrar接口,用于导入注册器,该类可以在代码运行时动态注册指定类的实例。

1598410081817

(5)引申(了解)

@import、@ImportResource、@PropertySource三个注解都是用于导入配置,有什么区别呢?

@import注解可以将普通类导入到spring容器中做管理;

@ImportResource(locations={}),与@import功能相似。只不过导入的是包含有definition配置的xml文件,而不是类。

@PropertySource可以导入property(key-value)文件到Spring容器中,用法:

@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
    @Autowired
    Environment env;
    
    @Bean
    public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setName(env.getProperty("testbean.name"));
        return testBean;
    }
}

二、解析@EnableAutoConfiguration

1598410278957

该注解用于开启自动配置,是 Spring Boot 的核心注解,是一个组合注解。所谓自动配置是指,其会自动找到其所需要的类,然后交给 Spring 容器完成这些类的装配。

  • @Import:用于加载 Spring Boot 中内置的及导入 starter 中 META-INF/spring.factories配置中的自动配置类。
  • @AutoConfigurationPackage:用于扫描、加载并注册自定义的组件类。
(1)@Import(AutoConfigurationImportSelector.class)

追踪 AutoConfigurationImportSelector的源码,我们可以发现确实是加载META-INF/spring.factories中的配置。

1598410729322

1598410802537

1598410828686

那么这个META-INF/spring.factories文件在哪里呢。所有的项目都依赖于spring-boot-starter,而spring-boot-starter又依赖于spirng-boot-autoconfigure,通过查看pom可以发现:

1598414704522

所以,我们在jar包中寻找spirng-boot-autoconfigure,

1598414798893

在spring.fatories中就看到一些默认的配置类,

keyorg.springframework.boot.autoconfigure.EnableAutoConfiguration

value配置类全路径

1598414898402

(2)@AutoConfigurationPackage

用于导入用户自定义类(即业务实现类),即自动扫描包中的类。

三、starter认知

通过以上的介绍,我们已经能够大致猜到在spring boot中是如何通过一个starter自动配置对象的了。

①通过@EnableAutoConfiguration读取到META-INF/spring.factories,这里边注册了所有需要加载的bean对应的配置类的全路径;

②spring会根据反射的原理,读取到配置类中使用@Bean声明的BeanDefinition,进而生成Bean对象放到IOC容器中。


通过以下两个例子我们再体会一下starter的配置。

(1)sping boot与redis整合

1598418337043

通过查看RedisAutoConfiguration,我们可以发现在此处创建了RedisTemplate实例。

1598418650854

(2)mybatis与spring boot整合

在 External Libraries 中找到 mybatis-spring-boot-starter 依赖。而该依赖又依赖于mybatis-spring-boot-autoconfigurigure。其 META-INF 中就有 spring.factories 文件,打开这个文件我们找到了 Mybatis 的自动配置类。

1598418809642

1598418857161

1598418901915

15984189834711598419001286

可以验证,我们以上的猜想starter=>spring.factories=>配置类=>生产Bean是正确的。

细心的人一定发现了以上有好多ConditionalOn开头的注解,它们是干什么用的呢?见名知意,没错,它们被称之为条件注解,只有符合注解条件时才会执行对应方法生成相应的Bean实例。

四、条件注解

常见的条件注解有:

@ConditionalOnClass():条件判断注解,其可以标注在类与方法上,表示当参数指定的类在类路径下存在时才会创建当前类的 Bean,或当前方法指定的 Bean。

@ConditionalOnMissionBean:条件判断注解,其可以标注在类与方法上,表示当容器中不存在当前类或方法类型的对象时,将去创建一个相应的 Bean。

@ConditionalOnBean():条件判断注解,其可以标注在类与方法上,表示当在容器中存在指定类的实例时才会创建当前类的 Bean,或当前方法指定的 Bean。

@ConditionalOnProperty():条件判断注解,其可以标注在类与方法上,表示配置文件中指定的属性满足条件时才会创建当前类的 Bean,或当前方法指定的 Bean。

五、手写一个starter

至此,我们应该可以手写一个starter了。可参考另一篇博客:

https://www.cnblogs.com/zomicc/p/13564586.html

"我们所要追求的,永远不是绝对的正确,而是比过去的自己更好"
原文地址:https://www.cnblogs.com/zomicc/p/13564585.html