@PropertySource、@ImportResource、@Bean

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/propertyhttp://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 ⭐⭐⭐⭐⭐(核心主推)

五、关键补充知识点

  1. @Configuration的小细节 :SpringBoot中配置类加@Configuration后,默认是单例模式 ------无论调用多少次@Bean方法,Spring只会创建一个Bean对象,保证容器中Bean的单例性;

  2. @Bean的注入优先级 :如果同一种类型有多个@Bean,注入时会报NoUniqueBeanDefinitionException,解决方式:

    • @Resource(name = "Bean名称")指定名称注入;
    • 给其中一个@Bean@Primary,设置为主Bean,Spring会优先注入;
  3. @PropertySource支持yml的坑 :默认不支持yml,如需支持,需自定义PropertySourceFactory,代码如下(了解即可,实际开发推荐用.properties):

    java 复制代码
    import 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")
  4. 配置类的扫描 :SpringBoot会自动扫描主启动类所在包及其子包下的@Configuration配置类,无需额外配置,如需扫描外部包,用@ComponentScan指定包路径。


六、总结

  1. @PropertySource是"加载配置文件" ,仅负责把自定义.properties的k-v加载到Spring环境,本身不创建Bean,需配合@Value/@ConfigurationProperties取值;
  2. @ImportResource是"兼容老xml",仅用于老项目迁移,新项目坚决不用,是过渡方案;
  3. @Bean是SpringBoot配置的"核心" ,替代xml和手动new对象,可结合@PropertySource实现配置驱动Bean ,是实际开发中自定义Bean的唯一推荐方式
  4. 三个注解的核心目的都是扩展SpringBoot的默认配置 ,而非修改原application.properties/yml,默认配置文件依然是SpringBoot的核心,负责框架自身的配置(如端口、数据库、日志等)。
相关推荐
Anastasiozzzz3 小时前
Redis的键过期是如何删除的?【面试高频】
java·数据库·redis·缓存·面试
老神在在0013 小时前
Token身份验证完整流程
java·前端·后端·学习·java-ee
王九思3 小时前
Java 内存分析工具 MAT
java·开发语言·安全
浅水壁虎3 小时前
任务调度——XXLJOB2(调度中心)
java·spring boot·spring
青火coding3 小时前
SOFAServerless架构的意义
java·运维·中间件·架构·serverless
夕除4 小时前
java--2
java·开发语言
源码获取_wx:Fegn08954 小时前
计算机毕业设计|基于springboot + vue景区管理系统(源码+数据库+文档)
java·vue.js·spring boot·后端·课程设计
李少兄4 小时前
Git 忽略文件机制:.gitignore 与 .git/info/exclude
java·git·elasticsearch
☀Mark_LY4 小时前
个人数据同步es小工具
java·elasticsearch