Spring 3.0 惰性初始化不支持 DefaultMessageListenerContainer?
我已经为 JMS 设置了 spring 配置。一切工作正常,除了我似乎无法将其延迟加载(请注意下面代码中的 default-lazy-init true )。如果我从下面的配置中注释掉 jmsContainer(DMLC),延迟加载将按预期工作。否则,它将实例化 DMLC,进而创建队列和连接工厂。
我缺少什么?
jmsContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-lazy-init="true">
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3:localhost:7001</prop>
</props>
</property>
</bean>
<bean id="queue" class="org.springframework.jndi.JndiObjectFactoryBean"
p:jndiTemplate-ref="jndiTemplate" p:jndiName="jms/queue"/>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"
p:jndiTemplate-ref="jndiTemplate" p:jndiName="jms/connectionfactory"/>
<bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver"
p:jndiTemplate-ref="jndiTemplate" p:cache="true" />
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"
p:autoStartup="false"
p:destination-ref="queue"
p:destinationResolver-ref="jmsDestinationResolver"
p:connectionFactory-ref="connectionFactory"
p:messageListener-ref="queueListener" />
<bean id="queueListener" class="com.blah.QueueListener"/>
</beans>
以及我用来驱动它的测试,DummyTest.java:
package blah;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:jmsContext.xml")
public class DummyTest {
@Test
public void shouldDoSomething() {
}
}
当 jmsContainer 被注释掉时,上面的测试通过。否则,我得到这个:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'jmsContainer' defined in class path resource [com/blah/config/jmsContext.xml]:
Cannot resolve reference to bean 'connectionFactory' while setting bean property 'connectionFactory';
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'connectionFactory' defined in class path resource [com/blah/config/jmsContext.xml]:
Invocation of init method failed; nested exception is javax.naming.NameNotFoundException:
Exception in lookup.: `jms/connectionfactory' could not be found.
[Root exception is weblogic.corba.cos.naming.NamingContextAnyPackage.NotFound: IDL:weblogic/corba/cos/naming/NamingContextAny/NotFound:1.0]
“connectionFactory”bean 被实例化为“jmsContainer”的依赖项,并且失败。注释掉“jmsContainer”后,“connectionFactory”不会被实例化。
jms 代码工作正常,但我故意重命名了 JNDI 名称,以便我可以看到事情何时开始。
I've setup a spring config for JMS. Things work fine, except I can't seem to get it to lazy load (notice the default-lazy-init true in the code below). If I comment out the jmsContainer(DMLC) from my config below, lazy loading works as expected. Otherwise, it will instantiate the DMLC, which in turn creates the queue and connection factory.
What am I missing?
jmsContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-lazy-init="true">
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3:localhost:7001</prop>
</props>
</property>
</bean>
<bean id="queue" class="org.springframework.jndi.JndiObjectFactoryBean"
p:jndiTemplate-ref="jndiTemplate" p:jndiName="jms/queue"/>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"
p:jndiTemplate-ref="jndiTemplate" p:jndiName="jms/connectionfactory"/>
<bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver"
p:jndiTemplate-ref="jndiTemplate" p:cache="true" />
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"
p:autoStartup="false"
p:destination-ref="queue"
p:destinationResolver-ref="jmsDestinationResolver"
p:connectionFactory-ref="connectionFactory"
p:messageListener-ref="queueListener" />
<bean id="queueListener" class="com.blah.QueueListener"/>
</beans>
And the test I'm using to drive it, DummyTest.java:
package blah;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:jmsContext.xml")
public class DummyTest {
@Test
public void shouldDoSomething() {
}
}
When jmsContainer is commented out, the test above passes. Otherwise, I get this:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'jmsContainer' defined in class path resource [com/blah/config/jmsContext.xml]:
Cannot resolve reference to bean 'connectionFactory' while setting bean property 'connectionFactory';
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'connectionFactory' defined in class path resource [com/blah/config/jmsContext.xml]:
Invocation of init method failed; nested exception is javax.naming.NameNotFoundException:
Exception in lookup.: `jms/connectionfactory' could not be found.
[Root exception is weblogic.corba.cos.naming.NamingContextAnyPackage.NotFound: IDL:weblogic/corba/cos/naming/NamingContextAny/NotFound:1.0]
The "connectionFactory" bean gets instantiated as a dependency of "jmsContainer" and it fails. With "jmsContainer" commented out, "connectionFactory" does not get instantiated.
The jms code works fine, but I have renamed my JNDI names on purpose so I can see when things get started.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,这相当晦涩难懂,但是
DefaultMessageListenerContainer
实现了Lifecycle
接口,并且实现该接口的 Bean 与上下文自己的生命周期相关联 - 当上下文启动时,生命周期-实现bean被初始化并启动。这意味着您的惰性初始化配置基本上被忽略。
OK, this is pretty obscure, but
DefaultMessageListenerContainer
implements theLifecycle
interface, and beans that implement this are tied into the context's own lifecycle - when the context starts up,Lifecycle
-implementing beans are initialised and started. This means that your lazy-init config is essentially ignored.解决办法是使用autoStartup为false。请参阅下面的代码。
〜夏姆
The solution is to use autoStartup to false. See the code below.
~Shyam