通常我们启动一个springboot项目会在启动方法中增加@SpringBootApplicatoin注解,该注解中包含了@EnableAutoConfiguration

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Inherited
  5. @SpringBootConfiguration
  6. @EnableAutoConfiguration
  7. @ComponentScan(excludeFilters = {
  8. @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  9. @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
  10. public @interface SpringBootApplication {
  11.  
  12. /**
  13. * Exclude specific auto-configuration classes such that they will never be applied.
  14. * @return the classes to exclude
  15. */
  16. @AliasFor(annotation = EnableAutoConfiguration.class)
  17. Class<?>[] exclude() default {};
  18.  
  19. /**
  20. * Exclude specific auto-configuration class names such that they will never be
  21. * applied.
  22. * @return the class names to exclude
  23. * @since 1.3.0
  24. */
  25. @AliasFor(annotation = EnableAutoConfiguration.class)
  26. String[] excludeName() default {};
  27.  
  28. /**
  29. * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
  30. * for a type-safe alternative to String-based package names.
  31. * @return base packages to scan
  32. * @since 1.3.0
  33. */
  34. @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
  35. String[] scanBasePackages() default {};
  36.  
  37. /**
  38. * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
  39. * scan for annotated components. The package of each class specified will be scanned.
  40. * <p>
  41. * Consider creating a special no-op marker class or interface in each package that
  42. * serves no purpose other than being referenced by this attribute.
  43. * @return base packages to scan
  44. * @since 1.3.0
  45. */
  46. @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
  47. Class<?>[] scanBasePackageClasses() default {};
  48.  
  49. }

那么@EnableAutoConfiguration是如何自动起作用的呢。我们先来看看@EnableAutoConfiguration的定义

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Inherited
  5. @AutoConfigurationPackage
  6. @Import(AutoConfigurationImportSelector.class)
  7. public @interface EnableAutoConfiguration {
  8.  
  9. String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
  10.  
  11. /**
  12. * Exclude specific auto-configuration classes such that they will never be applied.
  13. * @return the classes to exclude
  14. */
  15. Class<?>[] exclude() default {};
  16.  
  17. /**
  18. * Exclude specific auto-configuration class names such that they will never be
  19. * applied.
  20. * @return the class names to exclude
  21. * @since 1.3.0
  22. */
  23. String[] excludeName() default {};
  24.  
  25. }

我们看看EnableAutoConfiguration的注释定义:

  1. Enable auto-configuration of the Spring Application Context, attempting to guess and
  2. * configure beans that you are likely to need. Auto-configuration classes are usually
  3. * applied based on your classpath and what beans you have defined.

大概的意思是:容器尝试猜测你想配置的bean,然后自动加载。

很欣喜的发现了@EnableAutoConfiguration里面引用了@Import(AutoConfigurationImportSelector.class),直觉看起来像这个AutoConfigurationImportSelector里面引入了我们那些自动配置(数据源、拦截器)的类。

我们来看看AutoConfigurationImportSelector的定义:

  1. public class AutoConfigurationImportSelector
  2. implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
  3. BeanFactoryAware, EnvironmentAware, Ordered

原来AutoConfigurationImportSelector类实现了org.springframework.context.annotation.DeferredImportSelector

那么实现了该类的public String[] selectImports(AnnotationMetadata annotationMetadata)后,spring在解析bean的时候,就会自动调用该方法来加载拓展类,也就是selectImports方法返回的名称列表来加载类。

很容易起想到selectImports里面就返回了AutoEnableConfiguration的那些数据源、拦截器配置的类。!

接下来看看selectImports的具体实现:

  1. @Override
  2. public String[] selectImports(AnnotationMetadata annotationMetadata) {
  3. if (!isEnabled(annotationMetadata)) {
  4. return NO_IMPORTS;
  5. }
    //从org.springframework.boot.autoconfigure.AutoConfigurationMetadataLoader的loadMetadata加载要自动配置的资源数据
  1. AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
  2. .loadMetadata(this.beanClassLoader);
  3. AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
  4. autoConfigurationMetadata, annotationMetadata);
  5. return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
  6. }

看下AutoConfigurationMetadataLoader的源码看,可以看到默认加载的自动配置的路径为:/META-INF/spring-autoconfigure-metadata.properteis。

  1. final class AutoConfigurationMetadataLoader {
  2. //默认加载自动配置的文件位置
  3. protected static final String PATH = "META-INF/"
  4. + "spring-autoconfigure-metadata.properties";
  5.  
  6. private AutoConfigurationMetadataLoader() {
  7. }
  8.  
  9. public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
  10. return loadMetadata(classLoader, PATH);
  11. }
  12.  
  13. static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
  14. try {
  15. Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
  16. : ClassLoader.getSystemResources(path);
  17. Properties properties = new Properties();
  18. while (urls.hasMoreElements()) {
  19. properties.putAll(PropertiesLoaderUtils
  20. .loadProperties(new UrlResource(urls.nextElement())));
  21. }
  22. return loadMetadata(properties);
  23. }
  24. catch (IOException ex) {
  25. throw new IllegalArgumentException(
  26. "Unable to load @ConditionalOnClass location [" + path + "]", ex);
  27. }
  28. }
  29.  
  30. static AutoConfigurationMetadata loadMetadata(Properties properties) {
  31. return new PropertiesAutoConfigurationMetadata(properties);
  32. }
  33.  
  34. /**
  35. * {@link AutoConfigurationMetadata} implementation backed by a properties file.
  36. */
  37. private static class PropertiesAutoConfigurationMetadata
  38. implements AutoConfigurationMetadata {
  39.  
  40. private final Properties properties;
  41.  
  42. PropertiesAutoConfigurationMetadata(Properties properties) {
  43. this.properties = properties;
  44. }
  45.  
  46. @Override
  47. public boolean wasProcessed(String className) {
  48. return this.properties.containsKey(className);
  49. }
  50.  
  51. @Override
  52. public Integer getInteger(String className, String key) {
  53. return getInteger(className, key, null);
  54. }
  55.  
  56. @Override
  57. public Integer getInteger(String className, String key, Integer defaultValue) {
  58. String value = get(className, key);
  59. return (value != null) ? Integer.valueOf(value) : defaultValue;
  60. }
  61.  
  62. @Override
  63. public Set<String> getSet(String className, String key) {
  64. return getSet(className, key, null);
  65. }
  66.  
  67. @Override
  68. public Set<String> getSet(String className, String key,
  69. Set<String> defaultValue) {
  70. String value = get(className, key);
  71. return (value != null) ? StringUtils.commaDelimitedListToSet(value)
  72. : defaultValue;
  73. }
  74.  
  75. @Override
  76. public String get(String className, String key) {
  77. return get(className, key, null);
  78. }
  79.  
  80. @Override
  81. public String get(String className, String key, String defaultValue) {
  82. String value = this.properties.getProperty(className + "." + key);
  83. return (value != null) ? value : defaultValue;
  84. }
  85.  
  86. }
  87.  
  88. }

可以看到配置的默认加载的配载类有如下,这些类都被@Confiration注解,并且都自动创建了一些@Bean来使用组件的特性,通过这些自动创建的bean来代替我们系统中手动声明bean,达到加快开发效率的效果。

[org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration, org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration, org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration, org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration, org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration, org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration, org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration, org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration, org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration, org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration, org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration, org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration, org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration]

至此,springboot自动加载配置的原理也分析完毕。

springboot的@EnableAutoConfiguration起作用的原理的更多相关文章

  1. 007 SpringBoot的@EnableAutoConfiguration注解

    一:原理 1. 首先Spring Boot项目中都会如下启动类: @SpringBootApplication public class Application { public static voi ...

  2. SpringBoot:配置文件及自动配置原理

    西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处!防君子不防小人,共勉! SpringBoot ...

  3. if __name__ == 'main': 的作用和原理

    if __name__ == 'main': 功能 一个python的文件有两种使用的方法,第一是直接作为脚本执行,第二是import到其他的python脚本中被调用(模块重用)执行. if __na ...

  4. 【原创】uC/OS 中LES BX,DWORD PTR DS:_OSTCBCur的作用及原理

    LES BX, DWORD PTR DS:_OSTCBCur ;OSTCBCur->OSTCBStkPtr = SS:SP!!! ], SS ;将当前SS(栈的基地址)寄存器值存放至当前任务控制 ...

  5. synchronized与volatile的区别及各自的作用、原理(学习记录)

    synchronized与volatile的区别,它们的作用及原理? 说到两者的区别,先要了解锁提供的两种特性:互斥(mutual exclusion) 和可见性(visibility). 互斥:即一 ...

  6. EnableAutoConfiguration注解的工作原理(org.springframework.boot.autoconfigure.EnableAutoConfiguration=core.bean.MyConfig)

    EnableAutoConfiguration注解的工作原理(org.springframework.boot.autoconfigure.EnableAutoConfiguration=core.b ...

  7. volatile关键字的作用、原理

    在只有双重检查锁,没有volatile的懒加载单例模式中,由于指令重排序的问题,我确实不会拿到两个不同的单例了,但我会拿到"半个"单例. 而发挥神奇作用的volatile,可以当之 ...

  8. 面试题:volatile关键字的作用、原理

    在只有双重检查锁,没有volatile的懒加载单例模式中,由于指令重排序的问题,我确实不会拿到两个不同的单例了,但我会拿到“半个”单例. 而发挥神奇作用的volatile,可以当之无愧的被称为Java ...

  9. JAVA基础加强(张孝祥)_类加载器、分析代理类的作用与原理及AOP概念、分析JVM动态生成的类、实现类似Spring的可配置的AOP框架

    1.类加载器 ·简要介绍什么是类加载器,和类加载器的作用 ·Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader ...

随机推荐

  1. 一行python能干什么?

    我们都知道,python作为一个编程语言,它有一个最大的优势就是代码简短,那么一行python代码能实现哪些操作呢?一起来看看吧! 1.打印Hello World! 这是最基础的,相信不管学习哪一门语 ...

  2. Mongodb安装后在任务管理器中找不到这个服务

    今天安装mongodb,但是一开始在任务管理器中找不到这个服务,后来查询得知:稍微高一些的系统是需要通过管理员身份运行cmd命令行安装的. orz,找了好久才知道是这个问题. 2333 在任务管理的服 ...

  3. Nginx作为静态资源web服务之防盗链

    Nginx作为静态资源web服务之防盗链 首先,为什么需要防盗链,因为有些资源存在竞争对手的关系,比如淘宝的商品图片,不会轻易的让工具来爬虫爬走收集.但是如果使用防盗链,需要知道上一个访问的资源,然后 ...

  4. MySQL表内更新时,自动记录时间

    1.创建表: create table test_time(id int primary key not null,status  varchar(24),create_time datetime d ...

  5. shell 中执行Oracle查询和执行存储过程

    [oracle@master2 test]$ more b.sh #!/bin/sh #数据库地址 ip=192.168.1.250 port sid=orcl username=c##scott p ...

  6. js页面重定向跳转代码总结(待续)

    情形一:东八区,浏览器中文跳转 <script type="text/javascript"> var sLang = (navigator.language ? na ...

  7. chrome插件开发-notification API注意事项

    1.win10系统,在系统设置里面,设置开启Google Chrome通知 2.iconUrl必须设置,且图片为ico格式

  8. luogu3720 [AHOI2017初中组]guide[最短路]

    初中组..唉 题意有点误解,当前在x点走一步,gps产生代价条件是沿非x到n的最短路走. 直接倒着跑两遍$i\sim n$的两种最短路,然后枚举每条边走的时候是否可以在两种最短路上,不是就产生1个代价 ...

  9. strace分析启动流程

    strace -ttt /usr/local/mysql/bin/mysqld 2>&1 |tee 1.log vi 1.log 1 1530183737.761709 execve(& ...

  10. linux LVM逻辑卷管理

    什么是LVM LVM是逻辑卷管理(Logical Volume Manager)的简称,它是建立在物理存储设备之上的一个抽象层,允许你生成逻辑存储卷,与直接使用物理存储在管理上相比,提供了更好灵活性. ...