点进去源码发现html
先来看看每一个注解的意思java
能够发现它是由众多注解组合而成的,下面具体分析下这里每一个注解所起到的做用。spring
@Retention Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值:springboot
<context:component-scan>
,可以使用basePackages属性指定要扫描的包,及扫描的条件。若是不设置则默认扫描@ComponentScan注解所在类的同级类和同级目录下的全部类,因此咱们的Spring Boot项目,通常会把入口类放在顶层目录中,这样就可以保证源码目录下的全部类都可以被扫描到。@EnableAutoConfiguration 这个注解是让Spring Boot的配置可以如此简化的关键性注解。app
其实主要重要的注解就是标红的这三个注解:下面咱们着重分析这三个注解。框架
1)@ComponentScan:就像上面所说,ComponentScan通常在spring中主要是用于:maven
@ComponentScan用于类或接口上主要是指定扫描路径,spring会把指定路径下带有指定注解的类自动装配到bean容器里,会被自动装配的注解包括@Controller、@Service、@Component、@Repository等等,其做用等同于<context:component-scan base-package="com.maple.learn" />配置。ide
而在springboot中,若是你的其余包都在使用了@SpringBootApplication注解的main app所在的包及其下级包,则你什么都不用作,SpringBoot会自动帮你把其余包都扫描了,若是你有一些bean所在的包,不在main app的包及其下级包,那么你须要手动加上@ComponentScan注解并指定那个bean所在的包。(后面在解释在这里的原理)spring-boot
2)@SpringBootConfiguration :先来一张其源码截图工具
这里说明SpringBootConfiguration 实际上是对spring的@Configuration的封装,至关于一个配置类,注解主要标注在某个类上,至关于xml配置文件中的<beans>。并会将当前类内声明的一个或多个以@Bean注解的方法的实例归入到spring容器中,而且实例名就是方法名。自己其实也是一个IoC容器的配置类。
3)@EnableAutoConfiguration 这个才是重点,点击源码发现
先来聊聊这个注解:@AutoConfigurationPackage
AutoConfigurationPackage注解的做用是将 添加该注解的类所在的package 做为 自动配置package 进行管理。
1 static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { 2 3 @Override 4 public void registerBeanDefinitions(AnnotationMetadata metadata, 5 BeanDefinitionRegistry registry) { 6 register(registry, new PackageImport(metadata).getPackageName()); 7 }
它实际上是注册了一个Bean的定义。
new PackageImport(metadata).getPackageName(),它其实返回了当前主程序类的 同级以及子级 的包组件。
以上图为例,DemoApplication是和demo包同级,可是demo2这个类是DemoApplication的父级,和example包同级
也就是说,DemoApplication启动加载的Bean中,并不会加载demo2,这也就是为何,咱们要把DemoApplication放在项目的最高级中。
这里来谈谈其与componentScan的区别:
在默认的状况下就是将:主配置类(@SpringBootApplication
)的所在包及其子包里边的组件扫描到Spring容器中。
看看文档的这句话:
it will be used when scanning for code @Entity classes.
It is generally recommended that you place EnableAutoConfiguration (if you’re
not using @SpringBootApplication) in a root package so that all sub-packages
and classes can be searched.
好比说,你用了Spring Data JPA,可能会在实体类上写@Entity
注解。这个@Entity
注解由@AutoConfigurationPackage
扫描并加载,而咱们平时开发用的@Controller/@Service/@Component/@Repository
这些注解是由ComponentScan
来扫描并加载的。
简单理解:这两者扫描的对象是不同的。
4)下面来看看一个重中之重的注解:@EnableAutoConfiguration
老规矩进行这个重要注解以前,要先铺垫一些其用到的知识,否则的话,不能到时候懵懵懂懂的。接下来看看这个@Import这个注解,他是来干什么的呢?
@Import注释,根据字义,咱们能够理解为导入组件选择器自动配置,做用是将须要导入的组件以全类名的方式返回,这些组件将被添加到Spring容器中,如图:
自动配置类的做用,配置注入功能组件自动完成。
a.容许使用@Configuration注解的类
这个比较简单,若是明确知道须要引入哪一个配置类,直接引入就能够。
b.容许是实现ImportSelector接口的类
若是并不肯定引入哪一个配置类,须要根据@Import注解所标识的类或者另外一个注解(一般是注解)里的定义信息选择配置类的话,用这种方式。
c.Spring会把实现ImportSelector接口的类中的SelectImport方法返回的值注入到Spring容器中(即IOC容器)。这个方法的返回值必须是一个class的全类名的String[]。
比较典型的注解:
好吧,简单了解这个以后,下面来谈谈重点吧:
@EnableAutoConfiguration刚才已经贴了一张图了,点开源码以后就是
继续点击进去,你会发现:
一路点下去,发现AutoConfigurationImportSelector实现了父类接口ImportSelector,而且重写了父类的selectImports的方法。
在这个方法中,其实主要实现是看configurations这个里面返回的是什么东西就好了。
继续点进去这个方法
继续点击进去
这个时候,咱们就豁然开朗了,原来最终咱们是要找“META-INF/spring.factories”这个配置文件啊!
可是这个东西实在哪里呢,来看看咱们引入的mavenjar包吧。
原来是这个东西,看看里面是什么
是否是明白了,***AutoConfiguration,这个不就是咱们上面的注解的形式吗?
上图里面这么多的xxxAutoConfiguration就是咱们的这么久得出的结果,最终就是加载这么多的类的全路径,而后springboot内部就是实例化这些类并加载到容器里面,完成springboot应用启动时的自动配置。
来看看下面这样图,他们大神画的生动的图,让人豁然开朗:
借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration能够智能的自动配置功效才得以大功告成!
SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。
public abstract class SpringFactoriesLoader { //... public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) { ... } public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { .... } }
配合@EnableAutoConfiguration使用的话,它更可能是提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration做为查找的Key,获取对应的一组@Configuration类
上图就是从SpringBoot的autoconfigure依赖包中的META-INF/spring.factories配置文件中摘录的一段内容,能够很好地说明问题。
因此,@EnableAutoConfiguration自动配置的魔法骑士就变成了:从classpath中搜寻全部的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项经过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,而后汇总为一个并加载到IoC容器。
在来探讨一个问题:springboot的启动类其实基本上就两部分,一部分是spring-boot-starter,另外一部分是spring-boot-autoconfig,starter里面其实没有什么东西,就是依赖了autoconfig。
这么多的***AutoConfiguration,点进去过去会自动调到对应的启动类源码,在启动类中还有一个配置类***Properties,这个是默认自带的,例如:这个是activemq的默认配置类(默认的配置类)
在这里,ActiveMQAutoConfiguration的源码会关联这个配置文件,这样他们就能够连在一块儿,最直接的体现就是,咱们在application.properties或者applciation.yml中能够提示配置文件的属性
这样的话,整个启动类的思路就比较清晰了。
总结:
@ConditionalOnXX 条件判断注解,经过条件来判断这个类是否生效!
随便拿一个启动器举例子:
1:springboot启动的时候会加载大量的自动配置类。spring.factories
2:咱们就须要判断咱们的类是否在这个里面,若是不存在,咱们须要手动导入,若是存在,导入启动器便可。
3:咱们的配置文件(application.yml或者application.properties)之因此能够自动配置生效:
(1)xxxAutoConfiguation:自动配置类,根据条件@ConditionalOnXX来进行判断是否生效,若是生效则成功注入bean
(2)xxxProperties:封装配置文件的相关属性
4:给容器中自动配置属性的时候,会经过xxxProperties来获取某用户的配置文件中的属性,若是没有则使用默认,有则使用本身配置的。
(未完待续........)
本文引用文章声明:
原文连接:https://blog.csdn.net/neulily2005/article/details/83750027 -------CSDN博主「Mr.甘」
原文连接:https://blog.csdn.net/mapleleafforest/article/details/86623578----------CSDN博主「a maple leaf」
原文连接:http://www.javashuo.com/article/p-conjyivq-ey.html------那啥快看[博客园]
原文连接:http://www.imooc.com/article/275453?block_id=tuijian_wz---Java3y[慕课网]