我正在开发一个带有CDI的库。这很好用。但是当我尝试在项目中将此库用作包含的Jar时,CDI抱怨它无法解析父项目中定义的托管Bean的依赖关系。
MyProject的 - MyLib.jar - MyManagedBean
因此,MyLib需要注入一个带有构造型@foo的bean注释。此构造型应用于MyManagedBean。
@foo
public class MyManagedBean {
//...
}
我也将beans.xml添加到了我的父项目中。但就像有两个不同的CDI容器,MyLib无法访问MyProject。
有什么建议吗?
答案 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类。