如何从父类路径使用CDI托管bean

时间:2016-08-13 07:46:43

标签: java cdi

我正在开发一个带有CDI的库。这很好用。但是当我尝试在项目中将此库用作包含的Jar时,CDI抱怨它无法解析父项目中定义的托管Bean的依赖关系。

MyProject的     - MyLib.jar     - MyManagedBean

因此,MyLib需要注入一个带有构造型@foo的bean注释。此构造型应用于MyManagedBean。

@foo
public class MyManagedBean {
    //...
}

我也将beans.xml添加到了我的父项目中。但就像有两个不同的CDI容器,MyLib无法访问MyProject。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

我可以使用CDI扩展来访问父类文件。 Documentation和反思。

这是我使用的代码:

public class ConfigExtension implements Extension {

void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {
    Reflections reflections = new Reflections("");
    Set<Class<?>> types = reflections.getTypesAnnotatedWith(Tester.class);
    types.remove(info.scandi.fusion.cucumber.Tester.class);
    types.addAll(reflections.getTypesAnnotatedWith(Driver.class));
    types.addAll(reflections.getTypesAnnotatedWith(Worker.class));

    types.forEach(type -> {
        abd.addBean(new FusionBean((Class<T>) type, bm));
    });
}

}

public class FusionBean<T> implements Bean<T>, Serializable, PassivationCapable {

/**
 * 
 */
private static final long serialVersionUID = 1L;
private InjectionTarget<T> it;
private Class<T> bean;
private BeanManager bm;

public FusionBean(Class<T> workerClass, BeanManager bm) {
    this.bm = bm;
    bean = workerClass;
    AnnotatedType<T> at = bm.createAnnotatedType(bean);
    // use this to instantiate the class and inject dependencies
    it = bm.createInjectionTarget(at);
}

@Override
public T create(CreationalContext<T> creationalContext) {
    T instance = it.produce(creationalContext);
    it.inject(instance, creationalContext);
    it.postConstruct(instance);
    return instance;
}

@Override
public void destroy(T instance, CreationalContext<T> creationalContext) {
    it.preDestroy(instance);
    it.dispose(instance);
    creationalContext.release();
}

@Override
public Set<Type> getTypes() {
    Set<Type> types = new HashSet<>();
    //Use Apache Common Lang to get all Interfaces and Superclasses
    types.addAll(ClassUtils.getAllInterfaces(bean));
    types.addAll(ClassUtils.getAllSuperclasses(bean));
    return types;
}

@Override
public Set<Annotation> getQualifiers() {
    Set<Annotation> annotations = new HashSet<>();
    for (int i = 0; i < bean.getAnnotations().length; i++) {
        Class<? extends Annotation> possibleQualifier = bean.getAnnotations()[i].annotationType();
        if (bm.isQualifier(possibleQualifier)) {
            annotations.add(bean.getAnnotations()[i]);
        }
    }
    return annotations;
}

@Override
public Class<? extends Annotation> getScope() {
    for (int i = 0; i < bean.getAnnotations().length; i++) {
        Class<? extends Annotation> possibleScope = bean.getAnnotations()[i].annotationType();
        if (bm.isStereotype(possibleScope)) {
            for (Annotation annotation : possibleScope.getAnnotations()) {
                if (bm.isScope(annotation.annotationType())) {
                    return annotation.annotationType();
                }
            }
        }
    }
    return null;
}

@Override
public String getName() {
    return bean.getName();
}

@Override
public Set<Class<? extends Annotation>> getStereotypes() {
    Set<Class<? extends Annotation>> stereotypes = new HashSet<>();
    for (int i = 0; i < bean.getAnnotations().length; i++) {
        Class<? extends Annotation> possibleStereotype = bean.getAnnotations()[i].annotationType();
        if (bm.isStereotype(possibleStereotype)) {
            stereotypes.add(possibleStereotype);
        }
    }
    return stereotypes;
}

@Override
public boolean isAlternative() {
    for (int i = 0; i < bean.getAnnotations().length; i++) {
        if (bean.getAnnotations()[i].equals(Alternative.class)) {
            return true;
        }
    }
    return false;
}

@Override
public Class<?> getBeanClass() {
    return bean.getClass();
}

@Override
public Set<InjectionPoint> getInjectionPoints() {
    return it.getInjectionPoints();
}

@Override
public boolean isNullable() {
    return false;
}

@Override
public String getId() {
    return UUID.randomUUID().toString();
}

}

技巧是CDI Extension可以访问Parent Classpath。在这里,我使用Reflection api来获取使用我的框架的用户可以指定的Tester,Driver et Worker类。