图文并茂浅述 SpringBoot 的自动配置

1. Springboot的配置注入方式

  • 有两种:
  1. 配置文件为 application.properties
    这种方式是最近本的属性注入方式,早在学习spring的时候,就会大量用到这种属性注入方式,就是利用@Component+@Value注解的形式来进行属性注入。
  2. springBoot 新推荐的中,yml 文件,通过注解 @ConfigurationProperties 实现;为了后面浅述SpringBoot的自动配置原理,我们着重介绍这种方式。

首先,我们写一个 Pojo 类

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private int age;
    private String name;

    public Person() {
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
	// get、set方法,以及toString() 要写,此处省略...
}

@component我们知道,是Spring中的注解,用来像容器中注册一个Bean类型
@configurationProperties 则是SpringBoot的注解,那么他有什么用呢,括号内的参数有什么用呢? 不妨我们先测试一下
接下来写 yml配置文件:

person:
 age: 23
 name: chen

测试:

@Test
   void contextLoads() {
       System.out.println(person.toString());
   }

结果:
在这里插入图片描述

好了,我们可以看到,我们什么都没用在pojo类中做,只是书写了配置文件,我们的属性值已经导进去了。而这就归功于@configurationProperties,而括号中的 prefix 参数就是对应着yaml文件中的前缀,这样才能绑定成功。

2. SpringBoot 配置原理

好了,有了前面的铺垫,现在我们可以进入主题,那么SpringBoot到底做了什么,那么多的组件是如何启动成功的呢? 我们从启动类来看

2.1 @SpringBootApplication

图文并茂浅述 SpringBoot 的自动配置_第1张图片
我们点进@SpringBootApplication 注解,看到它的注解组成

第一-第四: Java的四个元注解,不做过多赘述。

我们点进 @SpringBootConfiguration
图文并茂浅述 SpringBoot 的自动配置_第2张图片
可以看到,这个注解本质上是说这个也是一个配置类
进入 @EnableAutoConfiguration
以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置 ;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效;
图文并茂浅述 SpringBoot 的自动配置_第3张图片
这里我们看最后面两个注解:

  1. @AutoConfigurationPackage
    图文并茂浅述 SpringBoot 的自动配置_第4张图片
    @import :Spring底层注解@import ,给容器中导入一个组件Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器 。
  2. @Import({AutoConfigurationImportSelector.class})
    见名知意, 自动配置导入选择器,那是如何选择的呢?
    点进去
    这是一个方法图文并茂浅述 SpringBoot 的自动配置_第5张图片
    我们重点看它这个方法:
    图文并茂浅述 SpringBoot 的自动配置_第6张图片
    在else 后面的代码中,调用了一个方法:
// 见名知意 获取候选配置,拿到了一个配置的集合
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

// 点进去
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

提到了一个文件,META-INF/spring.factories,我们全局搜索打开它

org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\

里面全部都是 XXXAutoConfiguration
我们随便点进去一个


@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({RabbitTemplate.class, Channel.class})
@EnableConfigurationProperties({RabbitProperties.class})
@Import({RabbitAnnotationDrivenConfiguration.class})
public class RabbitAutoConfiguration {
    public RabbitAutoConfiguration() {
    }
    ......
}






// 可以看到注解里面有一个 EnableConfigurationproperties,见名知意,开启属性自动配置,那么括号里面应该就是配置属性类,点进去
@ConfigurationProperties(
    prefix = "spring.rabbitmq"
)
public class RabbitProperties {
    private String host = "localhost";
    private int port = 5672;
    private String username = "guest";
    private String password = "guest";
    private final RabbitProperties.Ssl ssl = new RabbitProperties.Ssl();
    private String virtualHost;
    private String addresses;
    @DurationUnit(ChronoUnit.SECONDS)
    private Duration requestedHeartbeat;
    private boolean publisherReturns;
    private ConfirmType publisherConfirmType;
    private Duration connectionTimeout;
    private final RabbitProperties.Cache cache = new RabbitProperties.Cache();
    private final RabbitProperties.Listener listener = new RabbitProperties.Listener();
    private final RabbitProperties.Template template = new RabbitProperties.Template();
    private List<RabbitProperties.Address> parsedAddresses;

    public RabbitProperties() {
    }
    ......
}

到这里我们发现回到了第一部分我们讲解SpringBoot配置注入的地方
所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类 , 然后将这些都汇总成为一个实例并加载到IOC容器中。

注解的流程图
图文并茂浅述 SpringBoot 的自动配置_第7张图片

你可能感兴趣的:(框架,spring,boot,java,spring)