0

在 Arquillian 的测试中使用 Weld 1.1.13.Final....

假设我向一个领域注入了一些不稳定的东西。我希望拥有注入点的 bean 接收更改事件,例如可能发生更改的属性。考虑创建 CDI 扩展。

捕获 ProcessAnnotatedType 事件并查找在字段注入点上具有自定义注释的所有字段:

 <T> void pat(@Observes ProcessAnnotatedType<T> event, BeanManager bm) {
   final AnnotatedType<T> target = event.getAnnotatedType();

   for (AnnotatedField<? super T> field : target.getFields())
     if (field.isAnnotationPresent(Value.class)) {  // ignore that I don't check @Inject here for the moment
        CtClass wrapper = pool.get(target.getJavaClass().getName());
        ConstPool cp = wrapper.getClassFile().getConstPool();

        CtMethod m = CtNewMethod.make(....)
        ....
        wrapper.addMethod(m);

        event.setAnnotatedType(bm.createAnnotatedType(wrapper.toClass()));
     }
 }

此后甚至抓住了字段的所有注入点,并将底层的 WeldField 替换为与“包装器”类型相对应的新字段。否则 bean 验证失败。

但这仅适用于启动期间的东西设置,而不是例如 Arquillian 使用 Bean Manager 来初始化一个注入我的“包装”之一的类。事情失败了,因为 Bean Resolver 使用 Type 作为哈希键来查找 bean。

基本上,我认为我不能用额外的方法“屏蔽”由 CDI 注释(制成 bean)的类来接收自定义事件。本来会很酷,但类型是类型(即不知道如何代理或伪造 equals/hashCode)。

4

1 回答 1

0

知道了。结果证明 TypeSafeBeanResolver 解析器(至少 CDI Weld 实现)内的计算值函数(谷歌扩展)是智能的。如果我只是扩展课程:

 CtClass wrapper = pool.makeClass(target.getJavaClass().getName()+"Proxy");
 wrapper.setSuperclass(pool.get(target.getJavaClass().getName()));
 .....
 final AnnotatedType<T> other = bm.createAnnotatedType(wrapper
                    .toClass());

然后一切正常。测试在 bean 中捕获事件。将代码发布在带有评论的 Gist 上。

于 2013-12-19T15:07:17.427 回答