Spring能否注入Bean列表?如何基于单JMS连接创建多Session对应MessageProducer
问题根源
你原来的写法无法生效的核心原因是:Spring注入List<Session>时,只会收集容器中所有Session类型的Bean完成注入,而你定义的原型ScopeSession Bean默认仅会被初始化一次,不会自动生成指定数量的实例,自然无法满足需求。
可行实现方案
步骤1:新增yml配置项
在你的yml配置文件中添加Session数量配置:
jms: session-count: 5 # 可按需调整为你需要的Session数量
步骤2:定义资源持有类
因为原生List没有close方法,我们需要自定义资源持有类统一管理Session和Producer的生命周期:
import javax.jms.MessageProducer; import javax.jms.Session; import java.util.List; public class JmsResourceHolder implements AutoCloseable { private final List<Session> sessions; private final List<MessageProducer> producers; public JmsResourceHolder(List<Session> sessions, List<MessageProducer> producers) { this.sessions = sessions; this.producers = producers; } // 对外提供Producer列表供业务使用 public List<MessageProducer> getProducers() { return producers; } // 销毁方法:先关闭Producer再关闭Session,避免资源泄漏 @Override public void close() throws Exception { for (MessageProducer producer : producers) { if (producer != null) producer.close(); } for (Session session : sessions) { if (session != null) session.close(); } } }
步骤3:编写JMS配置类
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.jms.Connection; import javax.jms.MessageProducer; import javax.jms.Session; import java.util.ArrayList; import java.util.List; @Configuration public class JmsConfig { @Value("${jms.session-count}") private Integer sessionCount; // 替换为你自己的JMS目标队列/主题实例,也可单独声明为Bean注入 private final Destination yourDestination = /* 你的Destination对象 */; @Bean(destroyMethod = "close") public JmsResourceHolder jmsResourceHolder(Connection jmsConnection) throws Exception { List<Session> sessions = new ArrayList<>(); List<MessageProducer> producers = new ArrayList<>(); for (int i = 0; i < sessionCount; i++) { // 创建Session,两个参数可按需调整:是否开启事务、消息确认模式 Session session = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); sessions.add(session); // 基于当前独立Session创建对应Producer MessageProducer producer = session.createProducer(yourDestination); producers.add(producer); } return new JmsResourceHolder(sessions, producers); } }
步骤4:业务使用
需要使用Producer的地方直接注入JmsResourceHolder,调用getProducers()即可拿到所有Producer实例:
@Service public class JmsBusinessService { private final List<MessageProducer> producerList; public JmsBusinessService(JmsResourceHolder jmsResourceHolder) { this.producerList = jmsResourceHolder.getProducers(); } // 后续业务逻辑直接使用producerList即可 }
方案说明
- 全程复用同一个注入的JMS Connection,满足单连接多Session的要求
- Session数量完全由yml配置控制,调整无需修改业务代码
- Spring容器关闭时会自动调用
JmsResourceHolder的close方法,按顺序销毁Producer和Session,无需手动处理资源回收逻辑
内容的提问来源于stack exchange,提问作者user8473984
相关产品推荐
相关产品推荐

