【问题标题】:How does the constructor of a class implementing JMS MDB actually work?实现 JMS MDB 的类的构造函数实际上是如何工作的?
【发布时间】:2021-01-05 16:08:11
【问题描述】:

我试图了解 JMS 消息驱动 Bean 的生命周期,特别是因为它与实现它的 Java 类的构造函数有关。

我有一个实现javax.jms.MessageListener 的类JMSClass,这样我就可以拥有一个带有onMessage() 方法的消息驱动Bean,该方法在队列上侦听。 MDB 的容器是JBoss EAP 7.2 服务器。这是该类的简化和精简版本:

@ResourceAdapter(value = "wmq.jmsra.rar")
public class JMSClass implements MessageListener {

    private int x = 0;

    public JMSClass() {
        System.out.println("X: " + x);
    }

    @Override
    public void onMessage(Message message) {
        System.out.println("Value of x: " + ++x);
    }
}

x 属于 bean 实例,x 在调用 onMessage() 时继续成功递增。一旦我关闭并重新启动 JBoss 实例以及 bean 实例,x 将返回 0 并再次开始递增。这是预期的行为。

没想到的是构造函数在调用onMessage() 之前被调用了两次,并且值始终为0。所以我最终得到如下输出:

10:55:29,763 INFO  [stdout] (default-threads - 32) X: 0
10:55:29,861 INFO  [stdout] (default-threads - 32) X: 0
10:55:29,862 INFO  [stdout] (default-threads - 32) Value of x: 1
10:55:29,910 INFO  [stdout] (default-threads - 35) X: 0
10:55:29,910 INFO  [stdout] (default-threads - 35) X: 0
10:55:29,957 INFO  [stdout] (default-threads - 35) Value of x: 2
10:55:30,005 INFO  [stdout] (default-threads - 33) X: 0
10:55:30,005 INFO  [stdout] (default-threads - 33) X: 0
10:55:30,052 INFO  [stdout] (default-threads - 33) Value of x: 3
10:55:30,117 INFO  [stdout] (default-threads - 38) X: 0
10:55:30,117 INFO  [stdout] (default-threads - 38) X: 0
10:55:30,165 INFO  [stdout] (default-threads - 38) Value of x: 4
10:55:30,209 INFO  [stdout] (default-threads - 37) X: 0
10:55:30,209 INFO  [stdout] (default-threads - 37) X: 0
10:55:30,259 INFO  [stdout] (default-threads - 37) Value of x: 5
  1. 如果每次通过onMessage() 收到消息时都会调用构造函数,我希望每次都将x 的值设置回0(为什么首先要调用它两次?)李>
  2. 如果x 随每条消息递增,那么我希望构造函数在开始时仅在JBoss 容器实例化bean 时被调用一次。从那时起,应该只执行 onMessage() 代码。

有人可以提供一些关于这里发生的生命周期以及容器如何实例化 MDB 的见解吗?我发现没有任何资源提到 MDB 生命周期中的构造函数。

【问题讨论】:

    标签: java jms ejb


    【解决方案1】:

    MDB bean 的生命周期在EJB 3.2 spec 的第 5 章中进行了描述

    基本上,容器调用构造函数,注入依赖项,然后调用带有@PostConstruct 注释的方法(如果有)。然后将 bean 添加到池中以提供传入消息。

    请务必注意,池的任何实例都可以提供传入消息,因此您不能依赖 x 的值来计算消息。

    至于对构造函数的重复调用,这一定是 JBoss 的特定实现行为。可能是它不断向池中添加实例。也许它出于某种原因创建了某种动态代理或 MDB 的子类...如果您使用 @PostConstruct@PreDestroy 注释向 MDB 添加方法,您可以查看它是否是前者。

    【讨论】:

    • 我认为重复的构造函数调用必须是某种 JBoss 实现决定,所以当我有空闲时间时,我会玩弄 @PostConstruct@PreDestroy 来缩小范围
    猜你喜欢
    • 2014-03-11
    • 1970-01-01
    • 2014-06-30
    • 2013-09-19
    • 2016-07-24
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 2017-09-15
    相关资源
    最近更新 更多