基于spring-jms-3.1.1.RELEASE分析
org.springframework.jms.connection
spring使用jms
一般我们使用都是这样子
<bean name="jmsTransportListener" class="org.apache.activemq.transport.DefaultTransportListener"/>
</bean>
<bean id="jmsMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="transportListener" ref="jmsTransportListener"/>
</bean>
<bean id="jmsPooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
destroy-method="stop">
<property name="connectionFactory" ref="jmsMQConnectionFactory"/>
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="jmsPooledConnectionFactory"/>
</bean>
<bean id="chargeMessageContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<bean id="jmsCachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsPooledConnectionFactory"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsCachingConnectionFactory"/>
</bean>
今天不聊JmsTemplate 、listener和 PooledConnectionFactory ,这里面对connection的使用有两次,先看看这个包里面的功能
分类
org.springframework.jms.connection.SingleConnectionFactory
org.springframework.jms.connection.CachingConnectionFactory
org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter
org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy
org.springframework.jms.connection.DelegatingConnectionFactory
org.springframework.jms.connection.SmartConnectionFactory
SingleConnectionFactory
- JMS ConnectionFactory单例连接适配器,
调用createConnection返回相同的Connection,默认不调用{javax.jms.Connection
#close()}。根据JMS 连接器模型,此模式下线程安全(与JDBC相反)。单例模式下如果出现异常被断开,可以自动恢复共享连接。 - 可以直接传入特定的JMS
Connection,也可以通过给定ConnectionFactory懒加载创建一个Connection。单例工厂模式下支持JMS
1.1以及JMS 1.0.2 API。 - 使用JMS 1.0.2 API时,将根据运行时使用的JMS
API方法切换到queue/topic模式:createQueueConnection和createTopicConnection将分别创建queue/topic模式;而CreateConnection能创建支持同时服务两种模式的连接(JMS
1.1)。 - 在测试和独立环境比较有用,可以在多个org.springframework.jms.core.jmstemplate调用中保持使用相同的Connection,而不需要在下面再创建
ConnectionFactory 连接池。因此,它可以支持多事务,甚至是并发事务 - Spring的消息侦听器容器支持在每个侦听器容器实例中使用共享Connection
CachingConnectionFactory
- SingleConnectionFactory的扩展类,具有cacheProducers和cacheConsumers两种模式默认sessionCacheSize=1
- 因为定义了 volatile boolean active属性 并且对
cachedSessions(HashMap.class)的访问增加了synchronized控制 ,可认为
CachingConnectionFactory 是线程安全的。 - 添加javax.jms.session缓存以及javax.jms.messageProducer缓存的子类。默认reconnectOnException=true,即允许自动恢复Connection。
- 默认只缓存一个Session,在高并发环境的情况下,可调整sessionCacheSize的值,将根据需要创建Session。
- 仅支持JMS 1.1或更高版本。但是当JMS驱动程序是JMS1.1时也可以支持JMS1.0.2API的调用。
- 此ConnectionFactory要求显式关闭从其共享连接获取的所有会话。并且,只有使用过之后Session才能重用
- 缓存的Session从池中删除之后 MessageConsumers才会被关闭。在某些情况下,这可能会导致语义副作用。对于durable
subscriber,调用logical session.close()也将关闭subscription。不支持在同一Session
handle 上为同一subscription重新注册durable consumer;如有需要则请先关闭并重启cached
Session。
UserCredentialsConnectionFactoryAdapter
- ConnectionFactory QueueConnectionFactory, TopicConnectionFactory,
InitializingBean的子类 - 定义 NamedThreadLocal threadBoundCredentials(ThreadLocal) 保证线程安全
- javax.jms.ConnectionFactory的适配工厂,根据登录口令通过createConnection()隐式调用createConnection(用户名,密码)。其他操作也将由创建的ConnectionFactory来代理完成
- 一次配置 多次使用
- 在以下示例中,客户端代码使用指定的用户凭据隐式访问预配置的“myConnectionFactory”
<bean id="myTargetConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/mycf"/>
</bean>
<bean id="myConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="myTargetConnectionFactory"/>
<property name="username" value="myusername"/>
<property name="password" value="mypassword"/>
</bean>
如果username或者password为空,将调用createConnection获取连接
TransactionAwareConnectionFactoryProxy
- ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory的子类
由具体的ConnectionFactory 保证线程安全 - JMS {javax.jms.ConnectionFactory}的代理,添加对Spring管理的事务的识别(boolean
synchedLocalTransactionAllowed)。类似于J2EE提供的事务性JNDI ConnectionFactory
此代理可无缝参与Spring的事务管理,该过程对
Spring中JMS的消息传递是无感知的。但是,事务管理器(例如{JmsTransactionManager})仍然需要使用底层ConnectionFactory,而不是使用此代理。
当TransactionAwareConnectionFactoryProxy在ConnectionFactory代理/适配器链的最外层声明时,
TransactionAwareConnectionFactoryProxy可以直接委托给目标工厂或某些中间适配器例如
{UserCredentialsConnectionFactoryAdapter}。 - 委托{ConnectionFactoryUtils}时将自动参与线程绑定事务,例如由{JmsTransactionManager}管理。一个事务中返回Sessions时也降正常调用createSession和close
,即这是一个work on the transactional Session的操作。如果不是事务,则使用
ConnectionFactory 的默认方式 - 事务性JMS会话是要对每个连接都进行注册的。如果想在事务中共享相同的JMS会话,需要通过重用句柄或在下面配置{SingleConnectionFactory}共享JMS连接
- 事务会话代理(内部类TransactionAwareConnectionInvocationHandler返回)将返回{SessionProxy}的接口实现类以访问目标Session。此种类型仅用于访问vendor-specific的会话API或用于测试目的(例如,用于执行手动事务控制)。对于正常应用程序,只需使用标准JMS会话接口。
DelegatingConnectionFactory
- SmartConnectionFactory, QueueConnectionFactory,
TopicConnectionFactory, InitializingBean的子类 - 由具体委托的ConnectionFactory保证线程安全
- 所有调用委托给定的{javax.jms.ConnectionFactory}实现,在必要时可通过createConnection/createQueueConnection/createTopicConnection
(有参)指定ConnectionFactory(例如,当JMS 1.1 ConnectionFactory 运行基于JMS 1.0.2
API的代码时 ,例如ActiveMQ的PooledConnectionFactory)。 - 此类可以被继承,子类仅覆盖与ConnectionFactory相关的方法 (例如
createConnection/createQueueConnection/createTopicConnection) - shouldStopConnections属性可确认是否在关闭之前停止Connections。
对于连接池来说,这只是将连接释放返回到池中,而不是真正的停止。
SmartConnectionFactory
接口 继承自ConnectionFactory ,只增加了判断Connection是否需要停止的功能属性
总结
从以上可以看出 SingleConnectionFactory和 CachingConnectionFactory 稍显简单 容易使用,如果想实现jms的事务控制则需要在最顶层使用TransactionAwareConnectionFactoryProxy,至于UserCredentialsConnectionFactoryAdapter和 DelegatingConnectionFactory 也是某种意义上对ConnectionFactory的一种代理访问模式 这样可屏蔽外部调用时暴漏具体实现类 也可以自己写扩展类完成。