【SpringBoot】自动配置原理


首先看我们主程序,用到的注解是 @SpringBootApplication来告诉spring Boot这是一个springBoot 项目的启动位置。

@SpringBootApplication
public class EurekaServerApplication {

	public static void main(String[] args) {
		
		SpringApplication.run(EurekaServerApplication.class, args);
	}
}

其实SpringBootApplication 注解是一个组合注解,源码如下,最主要的是两个配置@SpringBootConfiguration ,@EnableAutoConfiguration ,下面具体来分析

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {};

    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};
}

1.@SpringBootConfiguration

查看@SpringBootConfiguration源码,其实它也就是@Configuration注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

@Configuration,它就是 JavaConfig 形式的 SpringIOC 容器的配置类,也是 SpringBoot 推荐使用配置形式,所以主程序类标注了 @SpringBootConfiguration 注解,其本身也就是一个配置类@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的,作用为:配置spring容器(应用上下文)。

2. @EnableAutoConfiguration

关于SpringBoot的自动配置原理,还是由@EnableAutoConfigration注解提供,以下是它的源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

2.1 @AutoConfigurationPackage
这个注解的主要功能是自动配置包,它会获取主程序类所在的包路径,并将包路径以及子包下的所有组件注册到SpringIoc容器中。

2.2 @Import({AutoConfigurationImportSelector.class})
@EnableAutoConfiguration 的关键功能也是这个 @Import 导入的配置功能,使用

SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader())

下的

classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");

来扫描META-INF/spring.factories 文件下的jar包,在spring-boot-autoconfigure:2.1.4.RELEASE.jar包下的META-INF下正好有个spring.factories文件:
在这里插入图片描述
打开 spring.factories 文件,找到 org.springframework.boot.autoconfigure.EnableAutoConfiguration 指定的自动配置类:

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,\

每一个 xxxAutoConfiguration 类都是容器中的一个组件,都加入到容器中,用它们来做自动配置。

2.3 自动配置分析
每一个 xxxAutoConfiguration都是容器中的一个组件,来做自动配置,下面以RabbitAutoConfiguration为例进行分析,看具体是如何自动配置的,下面是自动配置类RabbitAutoConfiguration的源码。在这个源码上我们可以看到@EnableConfigurationProperties({RabbitProperties.class}),开启属性自动配置

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

    @Configuration
    @ConditionalOnClass({RabbitMessagingTemplate.class})
    @ConditionalOnMissingBean({RabbitMessagingTemplate.class})
    @Import({RabbitAutoConfiguration.RabbitTemplateConfiguration.class})
    protected static class MessagingTemplateConfiguration {
        protected MessagingTemplateConfiguration() {
        }

        @Bean
        @ConditionalOnSingleCandidate(RabbitTemplate.class)
        public RabbitMessagingTemplate rabbitMessagingTemplate(RabbitTemplate rabbitTemplate) {
            return new RabbitMessagingTemplate(rabbitTemplate);
        }
    }
  }

在RabbitProperties.class中,通过@ConfigurationProperties(prefix = “spring.rabbitmq”)指定前缀是 spring.rabbitmq,在配置文件中的spring.rabbitmq中的属性和RabbitProperties中的属性一一对应,没有配置spring.rabbitmq用默认值。

@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 publisherConfirms;
    private boolean publisherReturns;
    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() {
    }

    public String getHost() {
        return this.host;
    }

    public String determineHost() {
        return CollectionUtils.isEmpty(this.parsedAddresses)?this.getHost():((RabbitProperties.Address)this.parsedAddresses.get(0)).host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return this.port;
    }
    ...

总结:
SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @ConfigurationProperties 等几个注解来进行自动配置完成的。

@EnableAutoConfiguration 开启自动配置,主要作用就是调用 Spring-Core 包里的 loadFactoryNames(),将 autoconfig 包里的已经写好的自动配置生成组件加载进IOC容器。

@Conditional 条件注解,通过判断类路径下有没有相应配置的 jar 包来确定是否加载和自动配置这个类。

@EnableConfigurationProperties 的作用就是,给自动配置提供具体的配置参数,只需要写在 application.properties 中,就可以通过映射写入配置类的 POJO 属性中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗琪小姐姐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值