Java EE 7:如何按名称模式注入所有类名以Cache结尾的Bean实例?
当然可行啦!在Java EE 7里,借助CDI(上下文与依赖注入)的强大能力,你完全能实现注入所有类名以Cache结尾的Bean实例。下面我给你一步步拆解具体操作,保证你能快速上手:
一、核心思路:用CDI的
Instance接口+编程式筛选 CDI的Instance接口可以帮你获取容器中符合条件的Bean实例集合,再配合类名判断就能精准筛选出目标Bean。如果想要更高效的筛选,还可以直接用BeanManager从Bean定义层面入手。
二、具体实现步骤
1. 先准备你的Cache类示例
先创建几个类名以Cache结尾的CDI管理Bean,比如:
@ApplicationScoped public class UserCache { public void loadUserCache() { System.out.println("加载用户缓存数据"); } } @ApplicationScoped public class ProductCache { public void loadProductCache() { System.out.println("加载商品缓存数据"); } }
注意:这些类一定要加上CDI的Scope注解(比如@ApplicationScoped),不然CDI容器不会管理它们哦。
2. 基础版:用Instance<Object>遍历筛选
在需要注入这些Cache Bean的业务类里,注入Instance<Object>,然后遍历并筛选类名以Cache结尾的实例:
@Inject private Instance<Object> allBeans; public void initAllCaches() { for (Object bean : allBeans) { Class<?> beanClass = bean.getClass(); // 小提示:如果Bean是CDI代理类,可能需要用getSuperclass()获取真实类名 if (beanClass.getSimpleName().endsWith("Cache")) { // 这里可以根据需求调用统一方法,比如先定义接口再强转 System.out.println("找到Cache类:" + beanClass.getSimpleName()); } } }
3. 进阶版:用BeanManager精准筛选
如果不想遍历所有Bean,想从容器的Bean定义层面直接筛选,效率更高,那就用BeanManager:
@Inject private BeanManager beanManager; public Set<Object> getAllCacheBeans() { Set<Object> cacheBeans = new HashSet<>(); // 获取容器中所有Bean的定义 Set<Bean<?>> allBeanDefs = beanManager.getBeans(Object.class, new AnnotationLiteral<Any>() {}); for (Bean<?> beanDef : allBeanDefs) { Class<?> beanClass = beanDef.getBeanClass(); if (beanClass.getSimpleName().endsWith("Cache")) { // 获取Bean的实例 Object instance = beanManager.getReference(beanDef, beanClass, beanManager.createCreationalContext(beanDef)); cacheBeans.add(instance); } } return cacheBeans; }
这种方式能直接跳过非目标Bean,还能避免代理类的类名干扰,更靠谱。
4. 优化建议:定义统一接口规范
为了更方便地操作所有Cache Bean,建议定义一个统一接口,比如:
public interface CacheInitializer { void initCache(); }
然后让所有Cache结尾的类实现这个接口:
@ApplicationScoped public class UserCache implements CacheInitializer { @Override public void initCache() { System.out.println("初始化用户缓存"); } }
这样筛选后,你就可以直接调用initCache()方法,不用做复杂的类型判断啦!
三、需要注意的细节
- 确保所有
Cache结尾的类都在CDI的扫描路径下,或者手动通过@Typed等方式让CDI识别。 - 处理代理类:如果你的Bean是代理对象(比如Scope是
@ApplicationScoped的Bean),获取类名时可以用beanClass.getSuperclass().getSimpleName(),或者通过BeanManager的Bean定义获取真实类型。 - 注意Bean的生命周期:如果是
@RequestScoped这类短生命周期的Bean,要确保在合适的上下文环境中获取实例。
内容的提问来源于stack exchange,提问作者Harold L. Brown
相关产品推荐
相关产品推荐

