applicationcontext 的 getbeanswithannotation 方法可获取所有被指定运行时注解标记的已注册 bean,返回非 null 空 map;要求注解含 @retention(runtime),支持类与方法级注解,但不扫描未注册类或递归元注解。

在 Spring 中,ApplicationContext 提供了 getBeansWithAnnotation(Class<a> annotationType)</a> 方法,用于一次性获取容器中所有被指定注解标记的 Bean(包括类上直接标注、或通过 @Component 等衍生注解间接携带该注解的 Bean)。
✅ 前提条件:注解必须是 @Retention(RetentionPolicy.RUNTIME)
Spring 在运行时通过反射扫描 Bean 的类/方法/字段上的注解,因此目标注解必须保留到运行时。例如:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) // 必须!
@Documented
public @interface MyService {
String value() default "";
}
✅ 正确使用 getBeansWithAnnotation
调用方式简单直接,返回一个 Map<string object></string>,其中 key 是 Bean 名称(beanName),value 是对应实例:
Map<string object> beans = context.getBeansWithAnnotation(MyService.class);
for (Map.Entry<string object> entry : beans.entrySet()) {
String beanName = entry.getKey();
Object bean = entry.getValue();
System.out.println("Bean name: " + beanName + ", instance: " + bean);
}</string></string>
- 如果没有任何 Bean 标记该注解,返回空 Map(不是
null) - 支持类级别注解(如
@MyService加在@Component类上) - 也支持方法级别注解(如加在
@Bean方法上),此时该方法产生的 Bean 会被纳入结果
⚠️ 注意事项与常见误区
这个方法只扫描“已注册进容器”的 Bean,不扫描未被 Spring 管理的类:
-
不扫描未被组件扫描覆盖的类:确保你的
@MyService类在@ComponentScan路径下,或显式用@Bean注册 -
不识别元注解传播:若
@MyService自身被@AliasFor或其他机制修饰,Spring 默认不递归解析元注解 —— 除非你用的是 Spring 5.2+ 并启用了AnnotationUtils.findAnnotation级别的逻辑(但getBeansWithAnnotation本身不支持) -
不包含代理对象的原始类型信息:如果 Bean 被 AOP 代理(如
@Transactional),返回的是代理对象,但注解仍是从原始类上读取的
? 替代方案:按类型 + 注解双重筛选(更灵活)
如果你需要进一步过滤(比如只要某个接口的实现类且带特定注解),可先用 getBeansOfType,再手动检查注解:
Map<string myserviceinterface> candidates = context.getBeansOfType(MyServiceInterface.class);
candidates.values().stream()
.filter(bean -> AnnotationUtils.findAnnotation(bean.getClass(), MyService.class) != null)
.forEach(System.out::println);</string>
这种方式更适合复杂条件组合,也便于调试和日志输出。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











