目录
- 1、使用@Value注解
- 2、使用@ConfigurationProperties注解
- 3、Environment方式
- 4、@Configuration注解+@Bean (还可以加@Import引入三方)
- 5、注入第三方bean
- IOC的几个注入bean的注解区别:
- 1. 使用@Bean注解在配置类中声明
- 2. 导入第三方提供的配置类
- 3. 使用Spring Boot的自动配置
- 4. 使用@ComponentScan扫描第三方bean
- 6、配置文件注入值数据校验
- 1. 使用@ConfigurationProperties 和 JSR-303/JSR-380 校验
- 2. @Validated 规则:
- 7、@PropertySource&@ImportResource&@Bean
- @PropertySource
- @ImportResource
- @Bean
- 6、配置文件占位符
- 1. 占位符语法
- 2. 使用Spring表达式语言(SpEL)
- 3. 引用环境变量和配置文件属性
- 4. 注意事项
- 7、配置注入找不到的默认值
- 使用@Value注解 + “:” 冒号
- 使用@ConfigurationProperties 声明成员并初始化
在Spring Boot中,配置文件(通常是application.properties或application.yml)的注入是一个核心功能,它允许开发者以声明式的方式配置应用程序。SpringBoot 提供了多种机制来实现配置文件的注入,包括使用:
@Value注解
@ConfigurationProperties注解
以及通过Environment
@Configuration类中的@Bean方法。
1、使用@Value注解
@Value注解可以直接用于字段、方法参数和构造器参数,以注入配置文件中的值。它适用于简单的配置项。
application.properties
app.name=MySpringBootApp
app.description=This is a demo application
Java类
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class MyAppConfig {@Value("${app.name}")private String appName;@Value("${app.description}")private String appDescription;// 省略getter和setter方法
}
2、使用@ConfigurationProperties注解
@ConfigurationProperties注解提供了一种更类型安全的方式来处理配置。你可以将配置文件中的一组相关属性绑定到一个Java
Bean上。
application.properties
myapp.name=MySpringBootApp
myapp.description=This is a demo application
myapp.settings.enabled=true
Java类
首先,定义一个配置类来绑定属性:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "myapp")
public class MyAppConfigProperties {private String name;private String description;private Settings settings = new Settings();// 省略getter和setter方法// 内部类来映射嵌套的属性public static class Settings {private boolean enabled;// 省略getter和setter方法}
}
在Spring Boot的启动类或配置类上添加@EnableConfigurationProperties注解来启用@ConfigurationProperties支持(对于Spring Boot 2.2及以上版本,这一步通常是可选的,因为Spring Boot会自动配置)。在更高版本的SpringBoot 中 @SpringBootApplication 注解 相当于三个注解的和
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableConfigurationProperties(MyAppConfigProperties.class)
public class MyAppConfigClass {// 类体可以为空
}
3、Environment方式
在Spring Boot中,Environment
抽象是Spring框架提供的一个接口,它允许你访问配置属性以及应用程序的环境。虽然Environment
不是一个专门用于注入配置的方式(像@Value或@ConfigurationProperties那样),但它可以在某些情况下非常有用,特别是当你需要访问低级别的配置信息或进行条件化配置时。
Environment 接口提供了多种方法来获取配置属性,包括通过键名(key)直接访问和通过解析占位符(placeholders)来访问。
注入 Environment
你可以通过Spring的依赖注入机制将Environment注入到你的bean中。这通常是通过构造函数注入或字段注入来完成的。
示例:通过构造函数注入 Environment
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;@Component
public class MyComponent {private final Environment environment;@Autowiredpublic MyComponent(Environment environment) {this.environment = environment;}public void doSomething() {// 使用 environment 来获取配置属性String someProperty = environment.getProperty("some.property.key");// 或者使用 resolvePlaceholders 来解析包含占位符的字符串String resolvedProperty = environment.resolvePlaceholders("${some.property.with.placeholder}");// 使用获取到的配置属性...}
}
注意事项
Environment 提供了对配置属性的广泛访问,但它不是类型安全的。如果你需要类型安全的配置绑定,建议使用@ConfigurationProperties。
resolvePlaceholders 方法允许你解析包含Spring占位符(如${…})的字符串。这在处理需要动态解析的配置值时非常有用。
Environment 还提供了对活动profiles的访问,这在进行条件化配置时非常有用。
当你需要访问Spring Boot的application.properties或application.yml文件中的配置时,Environment 是一个很好的选择,但它也可以访问其他来源的配置,如命令行参数、JNDI、servlet上下文参数等。
替代方案
对于简单的配置值,@Value 注解是一个更直接的选择。
对于复杂的配置对象,@ConfigurationProperties 注解提供了类型安全和更丰富的配置选项。
Environment 在Spring Boot中是一个强大的工具,但它应该根据具体需求谨慎使用。在大多数情况下,@Value 和 @ConfigurationProperties 将是更合适的配置注入方式。
4、@Configuration注解+@Bean (还可以加@Import引入三方)
在Spring
Boot中,@Configuration注解通常用于定义配置类,这些配置类通过@Bean注解的方法来声明和配置Spring容器中的bean。然而,如果你想要通过@Configuration方式注入配置(即注入从application.properties或application.yml等配置文件中读取的值),你通常会结合使用@Value或@ConfigurationProperties注解,而不是直接在@Configuration类中注入配置值。
不过,这里有一个概念上的澄清:@Configuration类本身不直接“注入配置”,而是声明和配置bean。配置值可以通过上述提到的注解注入到这些bean中,或者在配置类中用于条件化bean的创建。
使用@Value在@Configuration类中
尽管这不是@Configuration类特有的用法,但你可以在@Configuration类中的@Bean方法内部使用@Value注解来注入配置值。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyConfig {@Value("${my.config.value}")private String configValue;@Beanpublic MyBean myBean() {MyBean bean = new MyBean();bean.setConfigValue(configValue); // 使用注入的配置值return bean;}// MyBean的类定义...// 注意:这里需要有一个setConfigValue方法来设置configValue
}
5、注入第三方bean
当然以上的几种操作不仅可以注入配置,还可以注入第三方的bean,自己项目中手写的实体类或service可以通过 @Bean、@Controller、@Component、@Service、@Repository 方式注入,而从第三方软件依赖的bean则需要重新注入。
IOC的几个注入bean的注解区别:
顺便写下 @Bean、@Controller、@Component、@Service、@Repository 区别吧:
其实除了@Bean 其他几个没有本质区别目前为止,不乏SpringBoot后续会将引进更先进的方式以区分不同控制层,但现在除了@Bean外的其他注解只是预留在原理层无根本区别。
@Bean:
- @Bean 是用在方法上,用于声明一个Bean实例。
- 它通常用在配置类中的方法上,用于配置和初始化一个对象并将其添加到Spring容器中。
- @Bean方法可以有一个返回类型,该类型即为Bean的类型,Spring将会将该对象添加到容器中,并可以通过@Autowired或者@Inject注解进行注入。
@Controller:
- @Controller 是用于声明一个控制器类。
- 它用于标识一个Spring MVC控制器类,该类中的方法可以与不同的请求路径相对应,Spring MVC会将请求映射到对应的方法上进行处理。
@Component:
- @Component 是最通用的注解,用于声明一个普通的Spring Bean。
- 它是一个泛型注解,可以用于任意的类、接口、抽象类等,并将其标记为一个可被Spring容器管理的Bean。
- @Component注解通常作为其他注解的父注解,因此用于标记其他特定类型的Bean。
@Service:
- @Service 是 @Component 的一个特殊类型,用于声明一个服务类。
- 它通常用于标记业务逻辑层的类,并且通常与 @Autowired 注解一起使用,以便将所需的依赖注入到服务类中。
@Repository:
- @Repository 是 @Component 的一个特殊类型,用于声明一个数据访问层的类。
- 它通常用于标记数据访问对象(DAO),并且通常与 @Autowired 注解一起使用,以便将所需的依赖注入到数据访问对象中。
总结:
- @Bean 用于声明一个Bean实例;
- @Controller 用于声明一个控制器类;
- @Component 是最通用的注解,用于声明一个普通的Spring Bean;
- @Service 用于声明一个服务类;
- @Repository 用于声明一个数据访问层的类。
下面开始第三方bean注入的总结吧。
在Spring Boot中,注入第三方bean通常意味着你需要在你的应用程序中集成并使用来自外部库或框架的bean。这些bean可能不是由Spring
Boot自动扫描和管理的,因此你需要手动配置它们以便在你的应用程序中使用。以下是几种在Spring Boot中注入第三方bean的方法:
1. 使用@Bean注解在配置类中声明
如果第三方库没有提供Spring配置类,或者你需要对第三方bean进行自定义,你可以在你的配置类中使用@Bean注解来声明这些bean。
@Configuration
public class ThirdPartyBeanConfig {@Beanpublic ThirdPartyService thirdPartyService() {// 这里可能是直接返回第三方库的实例,或者是对其进行包装/自定义return new ThirdPartyServiceImpl();}
}
确保你的配置类被Spring Boot扫描到,通常是通过放在主配置类所在的包或其子包中
2. 导入第三方提供的配置类
如果第三方库提供了Spring配置类,你可以使用@Import注解来导入这些配置类。
@Configuration
@Import(ThirdPartyConfig.class) // 假设ThirdPartyConfig是第三方库提供的配置类
public class AppConfig {// 你的其他配置...
}// 第三方库的配置类可能看起来像这样
@Configuration
public class ThirdPartyConfig {@Beanpublic ThirdPartyService thirdPartyService() {return new ThirdPartyServiceImpl();}// 可能还有其他bean的声明...
}
3. 使用Spring Boot的自动配置
许多第三方库都提供了Spring
Boot的自动配置支持,这意味着它们会在满足特定条件时自动注册bean。在这种情况下,你通常只需要将第三方库的依赖添加到你的项目中,并确保你的@SpringBootApplication或@EnableAutoConfiguration注解被正确应用。
<!-- 在pom.xml中添加第三方库的依赖 -->
<dependency><groupId>com.example</groupId><artifactId>third-party-library-spring-boot-starter</artifactId><version>x.y.z</version>
</dependency>
// 你的Spring Boot启动类
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}// 无需额外配置,第三方bean将自动被注册
}
4. 使用@ComponentScan扫描第三方bean
如果第三方库中的bean被@Component、@Service、@Repository或@Controller等注解标记,并且你想要通过组件扫描来注册它们,你可以在你的配置类上使用@ComponentScan注解来指定扫描的包路径。但是,这通常不是推荐的做法,因为它依赖于第三方库的内部结构,这可能会在未来的版本中发生变化。
@Configuration
@ComponentScan(basePackages = {"com.example.thirdparty"}) // 假设第三方bean在这个包下
public class AppConfig {// 你的配置...
}
// 注意:这种方法通常不推荐,因为它依赖于第三方库的内部结构
总结 在实际应用中,最常见和推荐的方式是使用第三方库提供的Spring
Boot自动配置(如果可用),因为它简化了配置过程并减少了与第三方库内部实现的耦合。如果自动配置不可用,则可以考虑使用@Import注解导入第三方提供的配置类,或者在必要时使用@Bean注解在你的配置类中声明第三方bean。
6、配置文件注入值数据校验
在Spring Boot中,配置文件(如application.properties或application.yml)注入的值通常用于配置应用程序的各种参数。为了确保这些配置值是有效和安全的,进行数据校验是一个很好的实践。Spring
Boot 提供了几种方式来实现配置值的数据校验。
1. 使用@ConfigurationProperties 和 JSR-303/JSR-380 校验
@ConfigurationProperties注解是Spring
Boot中用于类型安全配置的一种方式。它允许你将配置文件中的属性绑定到一个POJO上,并且你可以在这个POJO上使用JSR-303(Bean
Validation API,在Java EE 7中引入)或JSR-380(Bean Validation 2.0,在Java EE
8中引入)注解来进行数据校验。
步骤:
定义配置类:
使用@ConfigurationProperties和@Validated(来自javax.validation.Valid,但通常使用@Validated来启用分组验证)注解来定义你的配置类。
添加校验注解:
在配置类的字段上使用校验注解(如@NotNull、@Min、@Size等)。
启用配置属性:
使用@EnableConfigurationProperties或将其注册为Spring的Bean来启用配置属性。
示例:
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;@ConfigurationProperties(prefix = "myapp")
@Validated // 开启校验
@Component // 或者使用@EnableConfigurationProperties(MyAppProperties.class)在配置类上
public class MyAppProperties {@NotNullprivate String name;@Min(value = 1, message = "Age must be greater than 0")private int age;// getter和setter
}// 如果不使用@Component,可以在配置类上使用@EnableConfigurationProperties
//@EnableConfigurationProperties(MyAppProperties.class)
//public class MyAppConfig {
//}
myapp.name=My Application
myapp.age=30
2. @Validated 规则:
-
空检查
@Null:验证对象是否为 null。@NotNull:验证对象是否不为 null,但无法检查长度为 0 的字符串。
@NotBlank:检查约束字符串是不是 null 以及被 Trim 的长度是否大于 0,只对字符串有效,且会去除前后空格。
@NotEmpty:检查约束元素是否为 NULL 或者 EMPTY(字符串长度不为 0、集合大小不为 0)。
-
布尔检查
@AssertTrue:验证 Boolean 对象是否为 true。@AssertFalse:验证 Boolean 对象是否为 false。
-
长度检查
@Size(min=, max=):验证对象(如 Array、Collection、Map、String)的长度是否在给定的范围之内。 -
日期检查
@Past:验证 Date 和 Calendar 对象是否在当前时间之前。@Future:验证 Date 和 Calendar 对象是否在当前时间之后。
-
数值检查
@Min(value=):验证 Number 和 String 对象是否大等于指定的值。@Max(value=):验证 Number 和 String 对象是否小等于指定的值。
@DecimalMin(value=):验证 Number 和 String 的值是否不小于指定的最小值。
@DecimalMax(value=):验证 Number 和 String 的值是否不大于指定的最大值。
@Digits(integer=,fraction=):验证 Number 和 String 的构成是否合法,integer 指定整数精度,fraction 指定小数精度。
-
正则表达式检查
@Pattern(regexp=):验证 String 对象是否符合正则表达式的规则。 -
其他检查
@Email:验证是否是邮件地址,如果为 null,不进行验证,算通过验证。 -
分组校验
@Validated 注解支持分组校验,可以在不同的业务场景中定义不同的校验规则。通过在方法参数前使用 @Validated(value = {分组接口.class}) 来指定校验分组。
7、@PropertySource&@ImportResource&@Bean
@PropertySource
@PropertySource注解用于指定一个或多个属性文件的位置,这些属性文件包含配置信息,如数据库连接详情、外部服务URL等。Spring容器在启动时会自动加载这些属性文件,并将它们的内容作为环境属性添加到Spring的Environment抽象中。这样,你就可以在应用程序的其他部分通过@Value注解或Environment
API来访问这些属性了。
@Configuration
@PropertySource("classpath:config.properties")
public class AppConfig {// 配置类内容...
}
在上面的例子中,@PropertySource注解指定了config.properties文件作为属性源,该文件位于类路径下。
@ImportResource
@ImportResource注解用于导入Spring的XML配置文件。虽然Spring Boot鼓励使用基于Java的配置(即使用@Configuration和@Bean注解),但在某些情况下,你可能仍然需要导入现有的XML配置文件。@ImportResource注解允许你这样做,它告诉Spring容器在启动时加载指定的XML文件。
@Configuration
@ImportResource("classpath:spring-context.xml")
public class AppConfig {// 配置类内容...
}
在上面的例子中,@ImportResource注解指定了spring-context.xml文件作为要导入的资源,该文件位于类路径下。
@Bean
@Bean注解用于在配置类中声明一个bean。当Spring容器启动时,它会查找所有带有@Configuration注解的类,并检查这些类中是否有带有@Bean注解的方法。对于每个这样的方法,Spring都会调用它,并将返回的对象注册为Spring容器中的一个bean。这样,你就可以在应用程序的其他部分通过依赖注入来使用这些bean了。
@Configuration
public class MyBeanConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}// 可能还有其他bean的声明...
}
在上面的例子中,myService方法被@Bean注解标记,因此Spring容器会调用该方法,并将返回的MyServiceImpl实例注册为一个bean。
总结
@PropertySource用于加载属性文件。
@ImportResource用于导入Spring的XML配置文件。
@Bean用于在配置类中声明bean。
这三个注解共同提供了Spring应用程序配置的强大工具集,允许你以灵活的方式组织和管理你的应用程序配置。
6、配置文件占位符
在Spring
Boot中,配置文件(如application.properties或application.yml)经常使用占位符(Placeholders)来引用其他配置值或环境变量。这些占位符允许你构建更灵活的配置,可以在不同的环境或部署之间共享和重用配置值。
1. 占位符语法
在application.properties文件中,占位符的语法是${…}。
例如:
app.name=MyApp
app.description=${app.name} is a great app
在application.yml文件中,占位符的语法也是${…},但在YAML中你需要确保值被引号包围,以避免解析错误:
app:name: MyAppdescription: "${app.name} is a great app"
2. 使用Spring表达式语言(SpEL)
虽然标准的${…}占位符通常足以满足需求,但Spring
Boot还支持更复杂的表达式,这些表达式使用Spring表达式语言(SpEL)。SpEL提供了更丰富的功能,如访问系统属性、环境变量、bean的属性等。但是,请注意,在application.properties和application.yml文件中直接使用SpEL的能力是有限的,因为这两个文件主要用于简单的键值对配置。
不过,在Spring Boot的@Value注解或XML配置中,你可以充分利用SpEL的功能。
3. 引用环境变量和配置文件属性
Spring Boot还允许你直接从环境变量和Java系统属性中引用值。例如:
引用环境变量
app.database.url=${DATABASE_URL:jdbc:h2:mem:testdb}
引用Java系统属性(通过-D选项在命令行中设置)
app.some.property=${system.someProperty:defaultValue}
这里,${DATABASE_URL:jdbc:h2:mem:testdb}表示尝试从环境变量DATABASE_URL中获取值;如果环境变量未设置,则使用默认值jdbc:h2:mem:testdb。
4. 注意事项
占位符的解析是在Spring Boot的配置加载阶段进行的,因此你不能在配置文件中使用循环引用。
在YAML文件中,由于YAML的语法特性,你可能需要使用引号来确保占位符被正确解析。
在使用SpEL时,请注意其使用上下文,因为并非所有地方都支持复杂的SpEL表达式。
占位符是Spring Boot配置中非常有用的特性,它们使得在不同环境之间共享和重用配置变得更加容易。
7、配置注入找不到的默认值
在Spring
Boot中,当配置注入(例如通过@Value注解或@ConfigurationProperties)找不到指定的配置项时,行为取决于你使用的注入方式和你的具体配置。默认情况下,Spring
Boot并不会为找不到的配置项提供一个通用的“默认值”机制,因为每个配置项的重要性和默认值都可能不同。不过,你可以通过几种方式来处理找不到配置项的情况。
使用@Value注解 + “:” 冒号
当使用@Value注解注入配置项时,如果找不到配置项,并且你希望提供一个默认值,你可以在@Value注解的字符串中使用:来指定默认值。
例如:
@Value("${some.property:defaultValue}")
private String someProperty;
在这个例子中,如果some.property在配置文件中不存在,那么someProperty字段将被赋值为defaultValue。
使用@ConfigurationProperties 声明成员并初始化
对于更复杂的配置对象,你通常会使用@ConfigurationProperties注解。在这种情况下,如果你想要为某个属性提供一个默认值,你只需要在配置类的相应字段上设置默认值即可。Spring Boot在绑定配置属性时会尊重这些默认值。
@ConfigurationProperties(prefix = "my")
public class MyProperties {private String propertyWithDefault = "defaultValue";// getter和setter
}
在这个例子中,如果my.property-with-default在配置文件中不存在,那么propertyWithDefault字段将保持其默认值defaultValue。
使用Spring Environment API
如果你需要更灵活地处理配置项的缺失情况,你可以在你的配置类中注入Environment对象,并使用它来检查某个配置项是否存在以及获取其值。这种方法给了你最大的灵活性,但也需要更多的代码。
@Autowired
private Environment env;public void someMethod() {String property = env.getProperty("some.property");if (property == null) {// 处理默认值或执行其他操作property = "defaultValue";}// 使用property...
}
注意事项
当使用@Value注解的默认值功能时,请注意不要在默认值中包含Spring的占位符(如${…}),因为这样做可能会导致意外的解析行为。
对于@ConfigurationProperties,确保你的配置类上使用了@EnableConfigurationProperties注解(如果你没有在@SpringBootApplication或其他配置类上全局启用它),并且你的配置类是一个标准的Spring组件(例如,通过@Component或@Configuration注解标记)。
在处理配置时,始终考虑配置项的敏感性和安全性。不要将敏感信息(如数据库密码)硬编码在默认值中。