在ActiveMQ的BrokerFilter中,如果调用setProperty设置了属性,在consumer中收到后是没有的,这个问题一两年前就有人提,参见 google 搜索结果 。而设置其属性,如setGroupId等,则有效。

查看了ActiveMQ的源码,发现传输中属性和setProperties调用的不是一个对象,前者(marshalledProperties)是用于传输的,后者(properties)是读取和设置的:

protected ByteSequence marshalledProperties;
protected Map properties;
 
    public Object getProperty(String name) throws IOException {
        if (properties == null) {
            if (marshalledProperties == null) {
                return null;
            }
            // 如果你先读取过属性,那么这里properties,marshalledProperties就都不为空了
            properties = unmarsallProperties(marshalledProperties);
        }
        return properties.get(name);
    }
 
    public void setProperty(String name, Object value) throws IOException {
        lazyCreateProperties();
        properties.put(name, value);
    }
 
    protected void lazyCreateProperties() throws IOException {
        if (properties == null) {
            if (marshalledProperties == null) {
                properties = new HashMap();
            } else {
                // 既然properties不为空,这句话永远不会被调用到(只要你先读取过属性)
                properties = unmarsallProperties(marshalledProperties);
                marshalledProperties = null;
            }
        }
    }

这就导致ActiveMQ不知道你修改过属性,因此到达consumer之后不会生效。

在BrokerFilter里面的修改方法很简单,在setProperty之后,强制将unmarsallProperties设置为空:

 public void send(ProducerBrokerExchange producerExchange, Message msg) throws Exception {
        message.setProperty("key","value");
	message.setUnmarsallProperties(null); // 就这句
        // ....
}