分类
spring spring-boot

Spring Boot注解

Spring Boot Annotations

1、概述

Spring Boot自动配置的特性使得Spring在配置上很简约。本文中,我们将围绕Spring中两个核心包org.springframework.boot.autoconfigure以及org.springframework.boot.autoconfigure.condition包中的注解展开介绍。

2、@SpringBootApplication

@SpringBootApplication是Spring Boot项目接触到的第一个注解,用与标识应用的启动主类。

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

从根本上讲@SpringBootApplication其实是@Configuration,@EnableAutoConfiguration和@ComponentScan三个注解的缩写,也可以认为@SpringBootApplication封装了上述三个注解。稍有些不同的是,@SpringBootApplication在封装@ComponentScan注解时,加入了一些默认的属性:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
		excludeFilters = {@ComponentScan.Filter(
				type = FilterType.CUSTOM,
				classes = {TypeExcludeFilter.class}
		), @ComponentScan.Filter(
				type = FilterType.CUSTOM,
				classes = {AutoConfigurationExcludeFilter.class}
		)}
)

也就是说在 Spring Boot项目中,完全可以使用上述注解代码段来代替@SpringBootApplication。当然了,实际的项目中肯定没有人这么做,试想谁又会舍近求远放着方便的不用,非要把简单的事情复杂化呢。

下面,让我们深入的了解一下Spring Boot的核心注解。

3、@EnableAutoConfiguration

@EnableAutoConfiguration的英文原意是:启用自动配置。该注解使得Spring Boot可以根据环境来自动检测并对项目进行一些自动化设置。比如当我们在pom.xml中同时引入Spring Data JPA以及H2数据库时,@EnableAutoConfiguration则会将Spring Data JPA的数据源自动的配置为H2。

需要注意的是该注解必须与@Configuration一起使用:

@Configuration
@EnableAutoConfiguration
class SpringBootAnnotationsConfig {}

4、条件注入(配置)

通常情况下,我们需要针对不同的环境(条件)来启用不同的配置,这一般被称为条件注入,可以借助本节中的条件注解来实现。

我们可以在使用@Configuration注解的类或使用@Bean注解的方法上放置条件注解,从而达到在特定的情况下使用特定的类或特定的方法的目的。在此,本文仅对其基本的使用方法进行介绍,预了解更多有关于本方面的知识,请访问此文

4.1. @ConditionalOnClass 以及@ConditionalOnMissingClass注解

@ConditionalOnClass表示:当某些类存在时,启用当前的配置;相反@ConditionalOnMissingClass表示:当某些类不存在时,启用当前配置。

@Configuration
@ConditionalOnClass(DataSource.class)
class MySQLAutoconfiguration {
    public MySQLAutoconfiguration() {
        System.out.println("DataSource.class存在")}
}

以下代码实现了:当DataSource.class存在时,Spring将使用该bean。

@Configuration
@ConditionalOnMissingClass("club.codedemo.springbootannotations.DataSource")
public class MySQLAutoconfiguration {
    public MySQLAutoconfiguration() {
        System.out.println("DataSource.class不存在“); }
}

以上代码实现了:当DataSource.class不存在时,Spring将使用该bean

4.2. @ConditionalOnBean以及@ConditionalOnMissingBean注解

除了可以基于类存在与否进行条件注入以外,还可以根据Bean是否存在来进行条件注入:

@Bean
@ConditionalOnBean(name = "dataSource")
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    // ...
}

以上代码实现了:当名称为dataSource的bean存在时,注入本方法返回的Bean。

@Bean
@ConditionalOnMissingBean(name = "dataSource")
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    // ...
}

以上代码实现了:当名称为dataSource的bean不存在时,注入本方法返回的Bean。

具体的验证代码请参阅本文提供的code demo。

4.3. @ConditionalOnProperty

使用@ConditionalOnProperty可以实现依据项目的属性值来进行注入。

@Bean
@ConditionalOnProperty(
    name = "usemysql", 
    havingValue = "local"
)
DataSource dataSource() {
    // ...
}

以上代码实现了:只有在项目的配置信息满足usemysql值为local时,注入该Bean。

4.4. @ConditionalOnResource

除根据项目的属性进行条件注入外,还可以根据项目资源文件夹中是否存在某配置文件来进行注入:

@Bean
//资源文件夹中存在mysql.properties文件时,该Bean生效
@ConditionalOnResource(resources = "classpath:mysql.properties")
Properties additionalProperties() {
    // ...
}
4.5.@ConditionalOnWebApplication以及@ConditionalOnNotWebApplication注解

@ConditionalOnWebApplication以及@ConditionalOnNotWebApplication注解可以基于当前应用程序是否为Web应用程序来进行配置。

@Bean
@ConditionalOnWebApplication
HealthCheckController healthCheckController() {
    // ...
}

如果当前应用属于Web应用,则上述Bean生效。

4.6. @ConditionalExpression

处理些稍复杂的注入需求,还可以使用@ConditionalExpression结合SpEL表达式来完成:

@Bean
@ConditionalOnExpression(${usemysql} && ${mysqlserver == 'local'})
DataSource dataSource() {
    // ...
}

@ConditionalOnExpression注解接收的是SpEL表达式,当该表达式返回true时,该Bean生效;返回false,不生效。

4.7. @Conditional

对于更复杂的条件,还可以通过@Conditional结合创建自定义类的方式来实现:

@Conditional(CustomCondition.class)
Properties additionalProperties() {
    //...
}

5. 结论

本从由SpringBootApplication注解入手,对Spring Boot的条件配置进行了讲解。在实际的使用过程中,还需要根据项目的实际情况选择适合的技术。我们说适用的就是最好的,切不可在实际的项目为了实现技术而实现技术。

本文资源: