我遇到了一些JMS调用代码,这些代码在其构造函数内部初始化JMS会话。调用代码实现ExceptionListener接口,并将对 this 的引用传递给连接工厂对象,如下所示:
public class JmsCode implements ExceptionListener {
private static final Logger logger = LoggerFactory.getLogger(JmsCode.class);
public JmsCode(String url, String username, String password, String trustStorePath, char[] trustStorePassword) throws JMSException {
ActiveMQSslConnectionFactory connectionFactory = new ActiveMQSslConnectionFactory(url);
connectionFactory.setUserName(username);
connectionFactory.setPassword(password);
connectionFactory.setTrustStore(trustStorePath);
connectionFactory.setTrustStorePassword(new String(trustStorePassword));
connectionFactory.setExceptionListener(this);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
@Override
public void onException(JMSException e) {
logger.error("Unexpected JMS exception caught", e);
}
}
我想知道从JmsCode构造函数传递对 this 的引用是否安全,因为该对象尚未完全构建。我遇到了类似的question,让我阅读了IBM's article on not publishing this during construction。尽管我同意他们的推理,但我不确定它是否适用于这种情况,因为异常侦听器唯一要做的就是通过静态成员和最终成员进行记录。上面的代码是否安全(忽略其他人试图更改异常侦听器方法以使用对象的某些实例状态)?
答案 0 :(得分:1)
这实际上是不安全的发布,并且从理论上讲,另一个对象可能会看到该对象处于不一致状态。
也就是说,尽管这不是一个好的模式(这里只是展示ExceptionListener
),但构造函数的逻辑表明该类实际上是在{{ 1}}引用转义(因为它没有要构造的),因此在这种情况下,没有任何错误。
答案 1 :(得分:0)
是否安全取决于对this
的引用可以在哪里逃脱 to 。如果作为此调用的结果,this
可以被另一个线程读取,那么它是不安全的。
如果要确保实例完全初始化以进行安全发布 ,并且要发布实例,则构造函数不是发布它的正确位置。相反,您需要创建一个Factory对象或静态工厂方法,以安全地构造该对象,然后在将其返回给调用方之前将其发布。
答案 2 :(得分:-1)
这是完全安全的。您只是通过this
引用,而不使用this
范围内的任何内容。
如果.setExceptionListener(this)
方法执行的不是设置者,那会出错。