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

Spring使用ApplicationContext报InstanceAlreadyExistsException异常

问题根因

抛出BeanCreationException嵌套InstanceAlreadyExistsException的核心原因是重复创建了两个独立的Spring应用上下文:

  • 代码中SpringApplication.run(DemoApplication.class, args)执行时,已经启动了完整的Spring Boot容器,自动完成了配置扫描、Bean注册、JMX管理Bean注册的全流程,其中就包括名为org.springframework.boot:type=Admin,name=SpringApplication的MBean。
  • 后续手动实例化new AnnotationConfigApplicationContext(ApplicationConfig.class)会启动第二个独立容器,启动过程中会再次尝试注册同名JMX MBean,而JMX规范不允许同标识MBean重复注册,直接触发异常。

除此之外你的代码里还有两个暂未触发的隐藏问题,等JMX冲突解决后就会报新的Bean创建错误:

  • UserDAO的构造方法用private修饰,Spring无法通过反射调用私有构造器实例化Bean
  • UserDAO没有添加@Component等Spring托管注解,也没有在配置类中通过@Bean显式注册,默认不会被容器识别管理
修复方案

根据你的学习目标二选一即可:

方案1:标准Spring Boot开发模式(日常开发推荐)

删除手动创建容器的冗余代码,直接使用SpringApplication.run返回的上下文即可。Spring Boot会自动扫描启动类所在包及子包下的@Configuration配置类,不需要手动加载:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
        // 可直接从ctx中获取Bean做测试
    }

}

同时修复UserDAO的问题:

  1. 将构造方法的访问修饰符从private改为public
  2. 给类添加@Component注解标记为Spring托管组件,单构造方法场景下Spring会自动注入构造器需要的DataSource参数,无需额外加@Autowired:
package com.example.demo;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;

@Component
public class UserDAO {
    private DataSource dataSource;

    public UserDAO(DataSource dataSource) {
        this.dataSource = dataSource;
    }
}

方案2:原生Spring注解容器练习模式

如果你是专门练习原生AnnotationConfigApplicationContext的使用逻辑,不想引入Spring Boot的自动配置能力,就不要使用@SpringBootApplication注解和SpringApplication.run启动方式,直接写纯main方法启动容器:

package com.example.demo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class DemoApplication {

    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class);
        // 后续Bean测试逻辑写在这里
    }

}

该场景下同样需要把UserDAO的构造方法改为public,要么给类加@Component让配置类上的@ComponentScan扫描到,要么直接在ApplicationConfig中写@Bean方法显式注册UserDAO。

临时规避方案(不推荐生产使用)

如果确实有特殊场景需要启动两个容器,可以通过配置关闭JMX自动注册绕过MBean冲突,在application.properties中添加如下配置:

spring.jmx.enabled=false

该方式只是掩盖了重复创建容器的问题,多余的容器会占用额外内存,还会导致Bean注入逻辑混乱,非必要不要使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:45:50