必须通过 applicationcontext 调用 getbeanswithannotation(),且需在容器启动完成后执行,推荐使用 applicationrunner 或监听 contextrefreshedevent 事件。

在 Spring Boot 启动类(即 `@SpringBootApplication` 标注的主类)中,不能直接调用 `application.getBeansWithAnnotation()`,因为 `SpringApplication` 实例本身没有这个方法 —— 这个方法属于 `ListableBeanFactory`(如 `ApplicationContext`)。正确做法是:先获取 `ApplicationContext`,再调用其 `getBeansWithAnnotation()` 方法。
确保 ApplicationContext 可用
启动类中的 `main` 方法默认只创建并运行 `SpringApplication`,此时上下文尚未完全初始化完毕。要在启动后执行逻辑,需借助 `ApplicationRunner` 或 `CommandLineRunner`,它们会在容器启动完成、所有 Bean 加载完毕后被回调。
- 直接在 `main` 方法里调用会报空指针或找不到 Bean —— 因为 `ApplicationContext` 还没准备好
- 不要试图在 `SpringApplication.run(...)` 返回前去查 Bean,必须等上下文刷新完成
使用 ApplicationRunner 获取带注解的 Bean
这是最常用、最安全的方式。实现 `ApplicationRunner` 接口,在 `run()` 方法中通过 `ApplicationContext` 查找:
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
@Bean
public ApplicationRunner findAnnotatedBeans(ApplicationContext context) {
return args -> {
// 查找所有标注了 @RestController 的 Bean(包括子注解,如 @Controller、@RequestMapping 等不在此列,仅精确匹配 @RestController)
Map<string object> beans = context.getBeansWithAnnotation(RestController.class);
beans.forEach((name, bean) ->
System.out.println("Bean name: " + name + ", type: " + bean.getClass().getSimpleName())
);
};
}
}</string>
注意:`getBeansWithAnnotation(Class annotationType)` 匹配的是**直接标注在类上的注解**(不是元注解),且只返回该注解类型本身(不递归查找 `@AliasFor` 或 `@Repeatable` 的变体)。
支持自定义注解和泛型 Bean 的处理
如果你定义了自定义注解(比如 `@MyService`),同样适用:
- 确保自定义注解本身用了 `@Target(ElementType.TYPE)` 和 `@Retention(RetentionPolicy.RUNTIME)`
- 若目标 Bean 是泛型(如 `MyService
`),`getBeansWithAnnotation()` 仍能正常返回其实例,但类型擦除后无法在运行时区分泛型参数 - 如果需要进一步按类型筛选,可结合 `context.getBeansOfType(...)` 或 `context.getBeanNamesForAnnotation(...)` + `context.getBean(name)`
替代方式:在 Configuration 类中初始化
如果逻辑较重或需注入其他 Bean,推荐抽离到 `@Configuration` 类中,并用 `@PostConstruct` 或 `InitializingBean`(更推荐 `@EventListener` 监听 `ContextRefreshedEvent`):
@Configuration
public class BeanScanConfig {
@EventListener
public void onContextRefresh(ContextRefreshedEvent event) {
ApplicationContext ctx = event.getApplicationContext();
Map<string object> beans = ctx.getBeansWithAnnotation(Scheduled.class); // 查所有 @Scheduled 方法所在类
// 注意:@Scheduled 是方法级注解,这里查的是标注了 @Scheduled 的类(Spring 不支持按方法注解查类)
// 如需查方法级注解,请用 ReflectionUtils 遍历所有 Bean 的方法
}
}</string>
⚠️ 提示:`getBeansWithAnnotation()` **只能查类级别注解**;方法/字段/参数级注解需手动反射扫描。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











