Spring Boot 自动配置

发布于 2024-04-12 00:00:29 字数 7609 浏览 31 评论 0

How does Spring Boot know what to configure?

-> 关键:spring boot 的条件化配置注解。
Spring Boot 会检测类路径上可用的依赖项,并相应地配置 Spring bean。有许多注释,例如 @ConditionalOnClass,@ConditionalOnBean,@ConditionalOnMissingBean 和 @ConditionalOnMissingClass,它们允许在这些类中为 Spring 配置类或 Spring bean 声明方法应用条件。

示例:
• 只有在类路径上有某个依赖项时才会创建 Spring bean。
使用 @ConditionalOnClass 并提供相关依赖项中包含的类。
• 仅当没有特定类型的 bean 或创建了某个名称时,才会创建 Spring bean。
使用 @ConditionalOnMissingBean 并指定要检查的 bean 的名称或类型。

What does @EnableAutoConfiguration do?

@EnableAutoConfiguration 注释启用 Spring Boot 自动配置。
Spring Boot 自动配置尝试基于类路径上可用的依赖关系创建和配置 Spring bean,以允许开发人员快速开始使用 Spring Boot 应用程序中的不同技术并减少样板代码和配置。

What does @SpringBootApplication do?

@SpringBootApplication 是一个便捷注释,可以应用于 Spring Java 配置类。
@SpringBootApplication 相当于 @Configuration,@EnableAutoConfiguration 和 @ComponentScan 三个注释。作用分别是标记为配置类,启用自动配置,启用组件扫描。

Does Spring Boot do component scanning? Where does it look by default?

Spring Boot 不进行组件扫描,除非一个已被 @Configuration 注解的配置类,同时也被 @ComponentScan 注解;或者,一个类使用 @SpringBootApplication 注解(该注解已包含 @ComponentScan 注解)。

可以使用 @ComponentScan 注解中的 basePackages 元素指定要扫描组件的基础包,或者通过使用 basePackageClasses 元素指定位于基础包中的一个或多个类来扫描组件。
如果没有使用上述元素,则将使用 @ComponentScan 注释的配置类作为基础包进行组件扫描。

How are DataSource and JdbcTemplate auto-configured?

@Configuration
public class SpringJdbcConfig {
    @Bean
    public DataSource mysqlDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc: mysql://localhost:3306/springjdbc");
        dataSource.setUsername("guest_user");
        dataSource.setPassword("guest_password");
        return dataSource;
    }
}

以定义 MySQL数据源为例:使用一个 @Configuration注解的配置类,定义一个 mysqlDataSource 的 bean,在方法里面配置数据库连接参数。

@Autowired     
private JdbcTemplate jdbcTemplate;

What is spring.factories file for?

SpringFactoriesLoader loads and instantiates factories of a given type from "META-INF/spring.factories" files which may be present in multiple JAR files in the classpath. The spring.factories file must be in Properties format, where the key is the fully qualified name of the interface or abstract class, and the value is a comma-separated list of implementation class names.

总之,SpringFactoriesLoader 会查找包含路径为 META-INF/spring.factories 的文件的 jar。

例如,在 spring-boot-autoconfigure.jar 的 META-INF/spring.factories 文件中,你将看到一系列的自动配置:

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

#Auto Configure  
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\  
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ ...

从中,以 org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration 为例进行深入探究:

@Configuration
@ConditionalOnClass({MongoClient.class})
@EnableConfigurationProperties({MongoProperties.class})
@ConditionalOnMissingBean(
    type = {"org.springframework.data.mongodb.MongoDbFactory"}
)
public class MongoAutoConfiguration {
    private final MongoClientOptions options;
    private final MongoClientFactory factory;
    private MongoClient mongo;

    public MongoAutoConfiguration(MongoProperties properties, ObjectProvider<MongoClientOptions> options, Environment environment) {
        this.options = (MongoClientOptions)options.getIfAvailable();
        this.factory = new MongoClientFactory(properties, environment);
    }

    @PreDestroy
    public void close() {
        if (this.mongo != null) {
            this.mongo.close();
        }
    }

    @Bean
    @ConditionalOnMissingBean(
        type = {"com.mongodb.MongoClient", "com.mongodb.client.MongoClient"}
    )
    public MongoClient mongo() {
        this.mongo = this.factory.createMongoClient(this.options);
        return this.mongo;
    }
}

留意这行: @EnableConfigurationProperties({MongoProperties.class})

@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {
    ...
    private String host;
    private Integer port = null;
    private String uri;
    private String database;
    ...
}

@ConfigurationProperties 将每个属性与特定前缀关联到 POJO。例如,属性 spring.data.mongodb.port 将映射到此类的 port 属性。

org.springframework.boot.autoconfigure.condition 包下面有很多关于条件化注解的类或者接口定义,以 @ConditionalOn 开头。

此外,还可以通过 ConfigurableApplicationContext#addApplicationListener 方法自定义 ApplicationContextInitializer s。

Ref:

How do you customize Spring auto configuration?

//TODO
Ref: https://www.baeldung.com/spring-boot-custom-auto-configuration 

What are the examples of @Conditional annotations? How are they used?

@Conditional(HibernateCondition.class)
Properties additionalProperties() {
  //...
}
static class HibernateCondition extends SpringBootCondition {
 
    private static String[] CLASS_NAMES
      = { "org.hibernate.ejb.HibernateEntityManager", 
          "org.hibernate.jpa.HibernateEntityManager" };
 
    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, 
      AnnotatedTypeMetadata metadata) {
  
        ConditionMessage.Builder message= ConditionMessage.forCondition("Hibernate");
        return Arrays.stream(CLASS_NAMES)
          .filter(className -> ClassUtils.isPresent(className, context.getClassLoader()))
          .map(className -> ConditionOutcome
            .match(message.found("class")
            .items(Style.NORMAL, className)))
          .findAny()
          .orElseGet(() -> ConditionOutcome
            .noMatch(message.didNotFind("class", "classes")
            .items(Style.NORMAL, Arrays.asList(CLASS_NAMES))));
    }
}

Ref:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

橘和柠

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文