SpringBoot中**@PropertySource、@ImportResource、@Bean三个注解的用法,核心是用它们扩展/替代默认的application配置文件**(并非直接修改原配置,而是补充/自定义配置),这三个注解解决的是不同场景的配置需求,其中**@Bean是SpringBoot最推荐的核心方式**,另外两个主要做兼容/配置文件扩展。
先明确一个前提:SpringBoot默认只自动加载application.properties/yml核心配置文件,这三个注解的出现,是为了解决默认配置不够用、兼容老Spring配置、纯代码替代配置文件这三类场景,所有示例基于基础SpringBoot项目(仅引入web依赖即可)。
一、@PropertySource:加载自定义的.properties配置文件
核心作用
专门让Spring加载默认配置文件以外的自定义.properties文件 ,把文件里的key=value加载到Spring的环境变量中,后续可以通过@Value或@ConfigurationProperties取值使用。
通俗理解
SpringBoot默认只认application.properties/yml,你想自己建个配置文件(比如my-config.properties)放业务配置,用这个注解告诉Spring:把这个文件也加载进来,里面的配置我要用到。
关键注意
默认不支持.yml/yaml文件(如需支持yml,需自定义配置工厂类,实际开发中极少用,因此重点讲.properties);可指定编码避免中文乱码。
注解核心属性
value/locations:指定自定义配置文件的类路径路径(最常用);encoding:指定文件编码(如UTF-8,解决中文乱码);ignoreResourceNotFound:是否忽略文件不存在,默认false(文件不存在会报错)。
代码示例:@PropertySource
步骤1:创建自定义.properties配置文件
在resources目录下新建my-config.properties,写入自定义配置:
properties
# 自定义业务配置
my.user.name=张三
my.user.age=20
my.user.desc=这是自定义配置文件的内容
步骤2:用@PropertySource加载配置文件
创建配置类 (或直接加在主启动类上,推荐单独建配置类,更规范),通过@PropertySource加载上述文件:
java
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
// 配置类标识(也可用@Component,效果一致)
@Component
// 加载自定义配置文件,指定UTF-8编码避免中文乱码
@PropertySource(value = "classpath:my-config.properties", encoding = "UTF-8")
public class MyPropertyConfig {
}
步骤3:读取加载的配置(两种常用方式)
方式1:@Value 单个取值(简单场景用)
创建Controller,注入并测试:
java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
// 用@Value("${配置key}")取值,:后是默认值(配置不存在时使用)
@Value("${my.user.name:默认名称}")
private String userName;
@Value("${my.user.age:18}")
private Integer userAge;
@Value("${my.user.desc:无描述}")
private String userDesc;
@GetMapping("/test/property")
public String testProperty() {
return "姓名:" + userName + ",年龄:" + userAge + ",描述:" + userDesc;
}
}
方式2:@ConfigurationProperties 批量绑定(推荐,适合多配置项)
创建实体类,批量绑定前缀为my.user的配置(需加@Component让Spring管理):
java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
// 让Spring管理该类
@Component
// 绑定配置的前缀(配置key的公共部分)
@ConfigurationProperties(prefix = "my.user")
public class UserProperties {
// 字段名与配置key的后缀一致(name对应my.user.name)
private String name;
private Integer age;
private String desc;
// 生成get/set方法(必须,否则无法绑定)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getDesc() { return desc; }
public void setDesc(String desc) { this.desc = desc; }
// 重写toString,方便测试
@Override
public String toString() {
return "UserProperties{" +
"name='" + name + '\'' +
", age=" + age +
", desc='" + desc + '\'' +
'}';
}
}
在Controller中注入实体类测试:
java
@RestController
public class TestController {
// 注入批量绑定的配置实体
@Autowired
private UserProperties userProperties;
@GetMapping("/test/property/batch")
public String testPropertyBatch() {
return userProperties.toString();
}
}
测试结果
启动项目,访问http://localhost:8080/test/property和http://localhost:8080/test/property/batch,能正常获取到自定义配置文件的内容,说明加载成功。
二、@ImportResource:导入传统Spring的xml配置文件
核心作用
让SpringBoot兼容老的Spring xml配置 ,把xml文件中通过<bean>标签定义的Bean,导入到SpringBoot的IOC容器中,让这些Bean被Spring管理并注入使用。
通俗理解
以前写SSM时,会用applicationContext.xml配置<bean id="" class="">创建Bean,现在SpringBoot推荐无xml开发 ,但如果有现成的xml配置不想重写,用这个注解告诉Spring:把这个xml文件导入进来,里面的Bean我还要用。
关键注意
SpringBoot官方强烈不推荐使用该注解 ,它仅做老项目兼容 ,新项目优先用@Bean替代xml配置。
注解核心属性
locations/value:指定xml配置文件的类路径路径(最常用);name:配置集的名称,几乎不用。
代码示例:@ImportResource
步骤1:创建传统Spring xml配置文件
在resources目录下新建spring-beans.xml,里面用<bean>定义一个普通Bean(比如业务类HelloService):
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 传统xml方式定义Bean:id是Bean名称,class是全类名 -->
<bean id="helloService" class="com.example.demo.service.HelloService"></bean>
</beans>
步骤2:创建xml中定义的Bean类
新建com.example.demo.service.HelloService:
java
package com.example.demo.service;
// 普通类,无任何注解(因为Bean由xml定义)
public class HelloService {
public String sayHello() {
return "Hello! 我是xml配置的Bean";
}
}
步骤3:用@ImportResource导入xml文件
必须加在SpringBoot的主启动类上(唯一有效位置),指定xml文件路径:
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
// 导入xml配置文件,让里面的Bean被Spring管理
@ImportResource(locations = "classpath:spring-beans.xml")
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
步骤4:注入并测试xml定义的Bean
在Controller中注入helloService(通过xml的id),测试是否能使用:
java
@RestController
public class TestController {
// 注入xml中定义的Bean
@Autowired
private HelloService helloService;
@GetMapping("/test/xml")
public String testXmlBean() {
return helloService.sayHello();
}
}
测试结果
访问http://localhost:8080/test/xml,返回Hello! 我是xml配置的Bean,说明xml中的Bean被成功加载到Spring容器中。
三、@Bean:纯代码方式创建Spring Bean(SpringBoot主推)
核心作用
替代xml中的<bean>标签 ,在配置类 中写方法,方法返回一个对象,给方法加@Bean注解,Spring就会把这个返回对象作为Bean放入IOC容器 ,后续可通过@Autowired/@Resource注入使用。
通俗理解
不用配置文件、不用xml,直接用代码"造对象",并告诉Spring:这个对象你帮我管理,别人要用直接拿 ,相当于代码版的<bean id="" class="">。
核心搭配
@Bean必须配合@Configuration注解使用 :@Configuration标识的类是SpringBoot的配置类 ,专门用来写@Bean方法,替代传统的xml配置文件,一个项目可以有多个配置类。
注解核心属性
name/value:自定义Bean的名称(id),数组类型,可指定多个别名;initMethod:Bean的初始化方法(相当于xml的init-method);destroyMethod:Bean的销毁方法(相当于xml的destroy-method);primary:设置为主Bean,解决同类型多个Bean的注入优先级问题。
关键默认规则
如果不指定name/value,Bean的默认名称是**@Bean标注的方法名**。
代码示例:@Bean(分2个场景,覆盖90%实际开发)
场景1:基础使用------纯代码创建Bean(替代xml)
步骤1:创建要被管理的Bean类(普通类,无注解)
还是用之前的HelloService,无需任何注解:
java
package com.example.demo.service;
public class HelloService {
public String sayHello() {
return "Hello! 我是@Bean配置的Bean";
}
}
步骤2:创建配置类,用@Bean创建Bean
新建配置类(推荐放在config包下),加@Configuration,写@Bean方法:
java
import com.example.demo.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 配置类标识:替代传统xml配置文件
@Configuration
public class MyBeanConfig {
// 方式1:默认Bean名称(方法名helloService)
@Bean
public HelloService helloService() {
return new HelloService(); // 方法返回Bean对象,Spring自动管理
}
// 方式2:自定义Bean名称(name/value指定,可多个别名)
/*
@Bean(name = {"myHelloService", "helloService2"})
public HelloService helloService() {
return new HelloService();
}
*/
}
步骤3:注入并测试
在Controller中注入,直接使用(默认用方法名注入,自定义名称则用名称注入):
java
@RestController
public class TestController {
// 注入@Bean创建的Bean(默认方法名helloService)
@Autowired
private HelloService helloService;
@GetMapping("/test/bean")
public String testBean() {
return helloService.sayHello();
}
}
场景2:高级使用------结合自定义配置动态创建Bean(实际开发常用)
把@PropertySource加载的自定义配置,动态设置到@Bean创建的Bean中,实现配置驱动Bean,这是实际开发中最常用的组合方式。
步骤1:修改自定义配置文件my-config.properties
增加Bean的配置项:
properties
# 自定义Bean的配置
my.service.name=业务服务Bean
my.service.version=v1.0
步骤2:创建带属性的Bean类
新建com.example.demo.service.MyService,包含属性和set/get方法:
java
package com.example.demo.service;
public class MyService {
private String name; // 服务名称
private String version; // 服务版本
// 业务方法
public String getServiceInfo() {
return "服务名称:" + name + ",版本:" + version;
}
// 必须生成set/get方法(用于动态赋值)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
}
步骤3:配置类中组合@PropertySource+@Bean
在配置类中加载自定义配置,并用@Value取值,动态设置到Bean中:
java
import com.example.demo.service.HelloService;
import com.example.demo.service.MyService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
// 1. 加载自定义配置文件
@PropertySource(value = "classpath:my-config.properties", encoding = "UTF-8")
// 2. 标识为配置类
@Configuration
public class MyBeanConfig {
// 3. 从自定义配置中取值
@Value("${my.service.name}")
private String serviceName;
@Value("${my.service.version}")
private String serviceVersion;
// 4. 动态创建Bean,设置配置属性
@Bean
public MyService myService() {
MyService myService = new MyService();
myService.setName(serviceName); // 给Bean设置配置值
myService.setVersion(serviceVersion);
return myService;
}
}
步骤4:注入并测试动态Bean
java
@RestController
public class TestController {
// 注入动态配置的MyService
@Autowired
private MyService myService;
@GetMapping("/test/bean/dynamic")
public String testDynamicBean() {
return myService.getServiceInfo();
}
}
测试结果
- 访问
http://localhost:8080/test/bean,返回Hello! 我是@Bean配置的Bean; - 访问
http://localhost:8080/test/bean/dynamic,返回服务名称:业务服务Bean,版本:v1.0;
说明Bean被动态配置并成功加载。
四、三个注解的核心对比(通俗总结)
为了让你快速区分,用表格清晰说明作用、使用场景、推荐程度,这是实际开发的核心参考:
| 注解 | 核心作用 | 通俗理解 | 主要使用场景 | SpringBoot推荐程度 |
|---|---|---|---|---|
| @PropertySource | 加载自定义.properties配置文件到Spring环境 | 给Spring加"额外的配置文件" | 配置项太多,想分文件管理(解耦) | ⭐⭐⭐⭐(常用) |
| @ImportResource | 导入传统Spring xml配置文件,加载xml中的Bean | 兼容老项目的xml配置 | 老SSM项目迁移到SpringBoot,不想重写xml | ⭐(仅兼容用) |
| @Bean | 纯代码创建Spring Bean,放入IOC容器 | 代码版的<bean>标签,造对象给Spring管理 |
新项目自定义Bean、动态配置Bean、替代xml | ⭐⭐⭐⭐⭐(核心主推) |
五、关键补充知识点
-
@Configuration的小细节 :SpringBoot中配置类加
@Configuration后,默认是单例模式 ------无论调用多少次@Bean方法,Spring只会创建一个Bean对象,保证容器中Bean的单例性; -
@Bean的注入优先级 :如果同一种类型有多个
@Bean,注入时会报NoUniqueBeanDefinitionException,解决方式:- 用
@Resource(name = "Bean名称")指定名称注入; - 给其中一个
@Bean加@Primary,设置为主Bean,Spring会优先注入;
- 用
-
@PropertySource支持yml的坑 :默认不支持yml,如需支持,需自定义
PropertySourceFactory,代码如下(了解即可,实际开发推荐用.properties):javaimport org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; import java.io.IOException; import java.util.List; public class YamlPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource()); return sources.get(0); } }使用时在
@PropertySource中指定工厂:java@PropertySource(value = "classpath:my-config.yml", factory = YamlPropertySourceFactory.class, encoding = "UTF-8") -
配置类的扫描 :SpringBoot会自动扫描主启动类所在包及其子包下的
@Configuration配置类,无需额外配置,如需扫描外部包,用@ComponentScan指定包路径。
六、总结
- @PropertySource是"加载配置文件" ,仅负责把自定义.properties的k-v加载到Spring环境,本身不创建Bean,需配合
@Value/@ConfigurationProperties取值; - @ImportResource是"兼容老xml",仅用于老项目迁移,新项目坚决不用,是过渡方案;
- @Bean是SpringBoot配置的"核心" ,替代xml和手动new对象,可结合
@PropertySource实现配置驱动Bean ,是实际开发中自定义Bean的唯一推荐方式; - 三个注解的核心目的都是扩展SpringBoot的默认配置 ,而非修改原
application.properties/yml,默认配置文件依然是SpringBoot的核心,负责框架自身的配置(如端口、数据库、日志等)。