Weld / CDI最好的调试技巧是什么?

Java EE 6的优点之一是新的dependency injection框架 – 带有Weld参考实现的CDI – 它促使我们以一种与实现无关的方式开始内部迁移到JSR-330,明确的目标是能够拥有核心jar被冻结,然后能够添加额外的jar子,提供新的模块替换核心jar中的function。

我现在正在与Weld一起完成上述工作,并且坦率地说,封面背后有太多的魔力。 无论是有效还是无效,默认情况下它不会提供很多帮助,因此您可以调查出错并修复它。

我希望有切换开关可以轻松实现以下function:

  • 扫描了哪些类路径条目以及在哪里? 结果是什么?
  • 什么豆可以注射哪个类?
  • 是什么导致给定的bean以后不被考虑? 一个给定的jar子?

换句话说,我需要更详细地看待决策过程。 出于某种原因,Guice不需要这样做,也许是因为魔法少得多,也许是因为错误消息非常好。

您如何调试Weld应用程序,以及它有多大帮助?

简短回答:CDI没有专用的调试选项(因为规范不需要这样的东西),也没有专门的Weld调试选项。

答案:你可以自己做很多事情。 熟悉CDI的扩展机制 ,你会发现你可以轻松(真的!)编写自己的扩展来调试你所需的信息

扫描了哪些类路径条目以及在哪里? 结果是什么?

收听ProcessAnnotatedType -Event

什么豆可以注射哪个类?

查询BeanManager。

是什么导致给定的bean以后不被考虑? 一个给定的jar子?

听取AfterBeanDiscovery ,看看你在BeanManager中得到了什么。 基本上,以下方案使ManageBean不符合注入条件:

我可以建议一些选择:

  • 降低记录阈值。 我不知道Weld使用了什么日志框架,但您可以看到并配置,例如, DEBUGINFO

  • 获取源代码并在BeanManager实现中放置断点(也许是BeanManagerImpl )。 它是CDI的主要类,几乎可以处理所有事情。

  • 尝试使用不同的实现(如果没有绑定应用程序服务器) – 例如OpenWebBeans 。 它的exception消息可能更好

  • 打开规范并阅读特定案例。 通常情况下,您错过了给定的前提条件 – 例如,注释必须具有特定的@Target ,否则它不会由CDI处理。

我可以确认Weld的exception消息令人失望。 我没有使用过Guice,但是在Spring中它们非常非常丰富。 有了Weld,我不得不参考上面的第4点(打开规范)并validation所有前提条件。 这是我最初的怀疑 – 即使规范看起来非常好,但实现方式也不会那么shiny(起初至少)。 但我想我会习惯这个。

Weld使用Simple Logging for Java(sl4j)。 如果您使用的是Tomcat,我建议您将sl4j-jdk14-xxxjar添加到应用程序类路径,并将以下行附加到apache-tomcat-7.0.x/conf/logging.properties

 org.jboss.weld.Bootstrap.level = FINEST org.jboss.weld.Version.level = FINEST org.jboss.weld.Utilities.level = FINEST org.jboss.weld.Bean.level = FINEST org.jboss.weld.Servlet.level = FINEST org.jboss.weld.Reflection.level = FINEST org.jboss.weld.JSF.level = FINEST org.jboss.weld.Event.level = FINEST org.jboss.weld.Conversation.level = FINEST org.jboss.weld.Context.level = FINEST org.jboss.weld.El.level = FINEST org.jboss.weld.ClassLoading.level = FINEST 

这将在控制台中生成大量调试,因此您最好选择特定的内容并注释掉其他行。

其他日志库(如log4j)可以使用各自的配置文件进行配置,并添加类似的级别。