You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Spring上下文获取已被@Autowired注入的Bean?

问题:如何从Spring上下文获取已被@Autowired注入的Bean?

我正在深入理解各类Spring Bean上下文,搭建了一个小型应用,支持两种Bean创建方式:

  • 通过XML配置文件注入
  • 通过@Autowired注解结合application.properties注入

从ClassPathXmlApplicationContext获取Bean正常,但手动创建上下文获取的Bean无法加载属性。

相关代码

application.properties

com.example.demo.Demo.beanName=BEAN_PROPERTIES

Bean定义

public interface IDemo {
    String getBeanName();
    void setBeanName(String beanName);
}

@Component
@Qualifier("demoAnnotation")
public class Demo implements IDemo {

    private static final Logger log = LoggerFactory.getLogger(Demo.class);

    @Value("${com.example.demo.Demo.beanName:BEAN_NAME_DEFAULT}")
    private String beanName;

    @Override
    public String getBeanName() {
        return beanName;
    }

    @Override
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
}

应用启动类

@SpringBootApplication
public class DemoApplication {

    private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);

    // 自动注入的Bean,打印beanName返回'BEAN_PROPERTIES'
    @Autowired
    private IDemo demoAnnotation;

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

    @Bean
    CommandLineRunner run() {
        return args -> {
            // 手动创建的上下文获取的Bean,getBeanName()返回'BEAN_NAME_DEFAULT'
            ApplicationContext ctx = new AnnotationConfigApplicationContext(DemoApplication.class);
            // demoAnnotation = (IDemo) ctx.getBean(Demo.class);

            // 打印自动注入的Bean返回`BEAN_PROPERTIES`
            log.info(demoAnnotation.getBeanName());
        };
    }
}

Gradle构建文件

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.5'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

更新内容:config.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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="demoXML" class="com.example.demo.Demo">
        <property name="beanName"><value>BEAN_XML</value></property>
    </bean>
</beans>

解决方法

问题根源

你在CommandLineRunner里手动创建了AnnotationConfigApplicationContext实例,这个新上下文和Spring Boot启动的主应用上下文完全独立。新上下文没有加载application.properties配置,所以@Value注解只能取到默认值BEAN_NAME_DEFAULT;而自动注入的demoAnnotation来自主上下文,自然能读取到配置文件中的值。

正确获取方式

  1. 直接注入主上下文
    不要手动创建新上下文,让Spring把主上下文注入到CommandLineRunner中,直接从主上下文获取Bean:

    @Bean
    CommandLineRunner run(ApplicationContext ctx) {
        return args -> {
            // 从主上下文获取Bean,能正确读取配置
            IDemo demoFromCtx = ctx.getBean(IDemo.class);
            log.info(demoFromCtx.getBeanName()); // 输出BEAN_PROPERTIES
        };
    }
    
  2. 同时加载XML配置(若需要)
    如果要让主上下文包含XML中的Bean,在启动类上添加@ImportResource注解引入XML配置:

    @SpringBootApplication
    @ImportResource("classpath:config.xml")
    public class DemoApplication {
        // ... 原有代码
    }
    

    之后可以通过ctx.getBean("demoXML")获取XML定义的Bean,其beanName值为BEAN_XML。


内容的提问来源于stack exchange,提问作者TMOTTM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:41:01