本文概览

在实际调试 Spring Boot 项目时,我们有时并不想修改注入逻辑、也不希望改动太多生产代码,只想在 Debug 阶段直接拿到某个 Bean,方便执行或观察内部变量,或者直接执行某个方法。

本文你将学会使用Evaluate Expression + Spring 的 ApplicationContext对象。

Evaluate Expression

注意:必须进入断点才可以看到。

Evaluate Expression 是 IntelliJ IDEA、Eclipse 等 IDE 在调试模式(Debug)下提供的一项非常强大的功能。

它允许开发者在程序运行暂停时,直接执行一段 Java 代码表达式,并立即查看结果,不需要修改源代码或重新启动程序。调试期可直接验证任意逻辑。

功能名称Evaluate Expression
使用场合Debug 模式下执行即时表达式
快捷键Alt + F8(Windows) / ⌥ + F8(Mac)
常见用途查看对象、调用方法、验证 Bean
特点不修改代码,可直接在内存中运行

IDEA进入断点后,代码区域点击鼠标右键 : 对表达式求值... 即可进入 Evaluate Expression

Evaluate Expression几乎可以输入任何合法的 Java 语句,如下:

类型示例
查看变量user.getName()orderList.size()
调用方法applicationContext.getBean(UserService.class).getUserById(1L)
新建对象new String("test").toUpperCase()
强制类型转换((UserService)applicationContext.getBean("userService")).getUserById(1L)
访问静态变量Math.PISystem.getenv()
临时定义变量(IDEA 支持 var)var u = new User("Tom"); u.getName();

需要学会使用高级一点的是:临时定义变量。

Evaluate Expression 支持完整的 Java 语法,只要当前断点作用域能访问到相关类。

正文 ApplicationContext

Spring 的核心是 IOC 容器,因此要做到这一点,只需要拿到容器对象 —— ApplicationContext


一、注入上下文对象

最直接的方法:通过 @Autowired 注入 ApplicationContext

@Autowired
private ApplicationContext applicationContext;

Spring 在启动后会自动将当前上下文注入进来,无需额外配置。

然后你就可以在断点调试或方法调用时,直接通过它拿到 Bean。


二、查看所有 Spring 管理的 Bean

如果你想了解容器里都注册了哪些 Bean,可以通过以下方法:

String[] beanNames = applicationContext.getBeanDefinitionNames();
for (String name : beanNames) {
    System.out.println(name);
}

这行代码会输出所有被 Spring 管理的对象名称。

在 IDEA 的 Debug 模式下,也可以直接 Evaluate:

applicationContext.getBeanDefinitionNames()

结果展示

例如在一个普通 Spring Boot 工程里,输出结果可能如下:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.event.internalEventListenerFactory
runApplication
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
globalExceptionHandler
aopConfig
asyncConfig
knife4jConfig
myBatisConfig
restTemplateConfig
...

可以看到,每个 Bean 的名称默认是首字母小写(即基于类名驼峰转写的规则)。

而那些以 internal 开头的 Bean,多为 Spring 框架自动注入的基础设施对象。


三、获取 Bean 实例(两种方式)单例 + 多例

当你知道了 Bean 的名称或类型之后,就可以从容器中把它取出来使用。

如果你是多例对象。你需要通过BeanName + Class 获取具体的对象。
可直接使用原生ApplicationContext.getBean(String beanName,Class<? extends Object> class)

方式一:通过 Bean 名称获取

Object aopConfig = applicationContext.getBean("aopConfig");

适用于:

  • 你知道 Bean 的名称;
  • 或多个 Bean 类型相同,但名称不同。

方式二:通过 Bean 类型获取

AopConfig aopConfig = applicationContext.getBean(AopConfig.class);

适用于:

  • 只有一个该类型的 Bean;
  • 你想直接拿强类型对象方便调用方法。

四、获取对象后直接调用方法

一旦拿到对应 Bean,就和写注入没区别,可以直接调用内部方法、触发逻辑。

AopConfig aopConfig = applicationContext.getBean(AopConfig.class);
aopConfig.initAopRules();

或者在 IDEA 的 Evaluate Expression 中直接执行:

applicationContext.getBean(AopConfig.class).initAopRules()

非常适合:

  • 调试私有逻辑;
  • 验证 Bean 是否正确加载;
  • 手动执行任务(无需重新运行)。

🔍 调试时的常用 Evaluate 表达式

目的Evaluate 示例
获取容器实例applicationContext
查看容器中 Bean 数量applicationContext.getBeanDefinitionCount()
列出所有 BeanapplicationContext.getBeanDefinitionNames()
获取单个 BeanapplicationContext.getBean("beanName")
按类型获取applicationContext.getBean(com.example.MyService.class)

小结

功能方法使用场景
查看所有 BeangetBeanDefinitionNames()了解项目全貌
按名称取 BeangetBean("beanName")多实例、通用工具
按类型取 BeangetBean(Class<T>)单实例、强类型调用
静态方式获取自定义 SpringCtxHolder静态工具/调试

静态类获取ApplicationContext

上述方式都需要你主动注入ApplicationContext。可以将该对象通过常量来获取

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * Copyright © zanglikun.com
 * 简要描述:
 * 本类是一个静态类,获取Spring的ApplicationContext对象。用于通过BeanName来获取Bean,直接调用其方法。
 * 主要初衷是 进入Debug模式内,直接使用 SpringCtxHolder.ctx 即可获取Spring的ApplicationContext对象。
 * @author zanglikun
 * @since 2026/3/2 16:16
 */
@Component
public class SpringCtxHolder implements ApplicationContextAware {
    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        ctx = applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return ctx.getBean(clazz);
    }

    // 如果你是多例对象。你需要通过BeanName + Class 获取具体的对象。
    // 可直接使用原生ApplicationContext.getBean(String beanName,Class<? extends Object> class)
}

普通调试

复杂高级调试

通过.class可直接获取到对象。但是通过IOC容器的BeanName获取的就是Object对象。传统方式无法调试。

var bean = (StringRedisTemplate) SpringCtxHolder.getBean("stringRedisTemplate");
bean.opsForValue().set("ok","1");
bean.opsForValue().get("ok");
特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤

免责声明:
本站文章旨在总结学习互联网技术过程中的经验与见解。任何人不得将其用于违法或违规活动!所有违规内容均由个人自行承担,与作者无关。