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,写入自定义配置:
# 自定义业务配置 my.user.name=张三 my.user.age=20 my.user.desc=这是自定义配置文件的内容步骤2:用@PropertySource加载配置文件
创建配置类(或直接加在主启动类上,推荐单独建配置类,更规范),通过@PropertySource加载上述文件:
importorg.springframework.context.annotation.PropertySource;importorg.springframework.stereotype.Component;// 配置类标识(也可用@Component,效果一致)@Component// 加载自定义配置文件,指定UTF-8编码避免中文乱码@PropertySource(value="classpath:my-config.properties",encoding="UTF-8")publicclassMyPropertyConfig{}步骤3:读取加载的配置(两种常用方式)
方式1:@Value 单个取值(简单场景用)
创建Controller,注入并测试:
importorg.springframework.beans.factory.annotation.Value;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassTestController{// 用@Value("${配置key}")取值,:后是默认值(配置不存在时使用)@Value("${my.user.name:默认名称}")privateStringuserName;@Value("${my.user.age:18}")privateIntegeruserAge;@Value("${my.user.desc:无描述}")privateStringuserDesc;@GetMapping("/test/property")publicStringtestProperty(){return"姓名:"+userName+",年龄:"+userAge+",描述:"+userDesc;}}方式2:@ConfigurationProperties 批量绑定(推荐,适合多配置项)
创建实体类,批量绑定前缀为my.user的配置(需加@Component让Spring管理):
importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.stereotype.Component;// 让Spring管理该类@Component// 绑定配置的前缀(配置key的公共部分)@ConfigurationProperties(prefix="my.user")publicclassUserProperties{// 字段名与配置key的后缀一致(name对应my.user.name)privateStringname;privateIntegerage;privateStringdesc;// 生成get/set方法(必须,否则无法绑定)publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicIntegergetAge(){returnage;}publicvoidsetAge(Integerage){this.age=age;}publicStringgetDesc(){returndesc;}publicvoidsetDesc(Stringdesc){this.desc=desc;}// 重写toString,方便测试@OverridepublicStringtoString(){return"UserProperties{"+"name='"+name+'\''+", age="+age+", desc='"+desc+'\''+'}';}}在Controller中注入实体类测试:
@RestControllerpublicclassTestController{// 注入批量绑定的配置实体@AutowiredprivateUserPropertiesuserProperties;@GetMapping("/test/property/batch")publicStringtestPropertyBatch(){returnuserProperties.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 version="1.0" encoding="UTF-8"?><beansxmlns="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是全类名 --><beanid="helloService"class="com.example.demo.service.HelloService"></bean></beans>步骤2:创建xml中定义的Bean类
新建com.example.demo.service.HelloService:
packagecom.example.demo.service;// 普通类,无任何注解(因为Bean由xml定义)publicclassHelloService{publicStringsayHello(){return"Hello! 我是xml配置的Bean";}}步骤3:用@ImportResource导入xml文件
必须加在SpringBoot的主启动类上(唯一有效位置),指定xml文件路径:
importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.annotation.ImportResource;// 导入xml配置文件,让里面的Bean被Spring管理@ImportResource(locations="classpath:spring-beans.xml")@SpringBootApplicationpublicclassDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DemoApplication.class,args);}}步骤4:注入并测试xml定义的Bean
在Controller中注入helloService(通过xml的id),测试是否能使用:
@RestControllerpublicclassTestController{// 注入xml中定义的Bean@AutowiredprivateHelloServicehelloService;@GetMapping("/test/xml")publicStringtestXmlBean(){returnhelloService.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,无需任何注解:
packagecom.example.demo.service;publicclassHelloService{publicStringsayHello(){return"Hello! 我是@Bean配置的Bean";}}步骤2:创建配置类,用@Bean创建Bean
新建配置类(推荐放在config包下),加@Configuration,写@Bean方法:
importcom.example.demo.service.HelloService;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;// 配置类标识:替代传统xml配置文件@ConfigurationpublicclassMyBeanConfig{// 方式1:默认Bean名称(方法名helloService)@BeanpublicHelloServicehelloService(){returnnewHelloService();// 方法返回Bean对象,Spring自动管理}// 方式2:自定义Bean名称(name/value指定,可多个别名)/* @Bean(name = {"myHelloService", "helloService2"}) public HelloService helloService() { return new HelloService(); } */}步骤3:注入并测试
在Controller中注入,直接使用(默认用方法名注入,自定义名称则用名称注入):
@RestControllerpublicclassTestController{// 注入@Bean创建的Bean(默认方法名helloService)@AutowiredprivateHelloServicehelloService;@GetMapping("/test/bean")publicStringtestBean(){returnhelloService.sayHello();}}场景2:高级使用——结合自定义配置动态创建Bean(实际开发常用)
把@PropertySource加载的自定义配置,动态设置到@Bean创建的Bean中,实现配置驱动Bean,这是实际开发中最常用的组合方式。
步骤1:修改自定义配置文件my-config.properties
增加Bean的配置项:
# 自定义Bean的配置 my.service.name=业务服务Bean my.service.version=v1.0步骤2:创建带属性的Bean类
新建com.example.demo.service.MyService,包含属性和set/get方法:
packagecom.example.demo.service;publicclassMyService{privateStringname;// 服务名称privateStringversion;// 服务版本// 业务方法publicStringgetServiceInfo(){return"服务名称:"+name+",版本:"+version;}// 必须生成set/get方法(用于动态赋值)publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicStringgetVersion(){returnversion;}publicvoidsetVersion(Stringversion){this.version=version;}}步骤3:配置类中组合@PropertySource+@Bean
在配置类中加载自定义配置,并用@Value取值,动态设置到Bean中:
importcom.example.demo.service.HelloService;importcom.example.demo.service.MyService;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.PropertySource;// 1. 加载自定义配置文件@PropertySource(value="classpath:my-config.properties",encoding="UTF-8")// 2. 标识为配置类@ConfigurationpublicclassMyBeanConfig{// 3. 从自定义配置中取值@Value("${my.service.name}")privateStringserviceName;@Value("${my.service.version}")privateStringserviceVersion;// 4. 动态创建Bean,设置配置属性@BeanpublicMyServicemyService(){MyServicemyService=newMyService();myService.setName(serviceName);// 给Bean设置配置值myService.setVersion(serviceVersion);returnmyService;}}步骤4:注入并测试动态Bean
@RestControllerpublicclassTestController{// 注入动态配置的MyService@AutowiredprivateMyServicemyService;@GetMapping("/test/bean/dynamic")publicStringtestDynamicBean(){returnmyService.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):
使用时在importorg.springframework.boot.env.YamlPropertySourceLoader;importorg.springframework.core.env.PropertySource;importorg.springframework.core.io.support.EncodedResource;importorg.springframework.core.io.support.PropertySourceFactory;importjava.io.IOException;importjava.util.List;publicclassYamlPropertySourceFactoryimplementsPropertySourceFactory{@OverridepublicPropertySource<?>createPropertySource(Stringname,EncodedResourceresource)throwsIOException{List<PropertySource<?>>sources=newYamlPropertySourceLoader().load(resource.getResource().getFilename(),resource.getResource());returnsources.get(0);}}@PropertySource中指定工厂:@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的核心,负责框架自身的配置(如端口、数据库、日志等)。