如何以编程方式动态设置MDB

时间:2012-07-12 07:30:07

标签: java spring jms message-driven-bean

我在独立环境中使用Spring3.1。

我用这种方式用jms模板设置主题:

<bean id="mm1sessionsTopicSendingTemplate" class="org.springframework.jndi.JndiObjectFactoryBean"
    depends-on="jmsServerManagerImpl">
    <property name="jndiName">
        <value>/topic/mm1sessionsTopic</value>
    </property>
</bean>

对于本主题,我用这种方式设置MDB和DefaultMessageListenerContainer:

<bean id="mm1sessionDispatcherListener"
        class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="pubSubDomain" value="true" />
        <property name="concurrentConsumers" value="1" />
        <property name="destination" ref="mm1sessionsTopicSendingTemplate" />
        <property name="messageListener" ref="mm1SessionMDB" />
        <property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
    </bean>

通过这种方式,我必须通过xml:

将mm1SessionMDB设置为高级
<bean id="mm1SessionMDB" class="com.mdb.SessionMDB">
        <property name="feedPropertiesDTO" ref="feedListenerMarketMaker1Properties" />

    </bean>

但我需要我的应用程序来创建MDB实例以编程方式

我的意思是我想通过代码创建mdb,因为每个MDB对于它将从主题中检索的消息具有不同的验证值(通过feedPropertiesDTO)

基本上我将拥有相同逻辑的MDB池,但每个都将具有不同的属性。 MDB的创建时间必须在运行时。

可能吗?

感谢, 射线。

1 个答案:

答案 0 :(得分:0)

我认为您可以使用工厂方法来即时化MDB bean并使用方法

Object getBean(String name, Object... args) throws BeansException;
代码中 ApplicationContext

以编码方式实例化bean。

据我所知,这个方法允许你将参数路径化为工厂方法。

这里有关于此方法的java doc中所说的内容:

返回指定bean的实例,该实例可以是共享的或独立的。

  

允许指定显式构造函数参数/工厂方法   参数,覆盖。中的指定默认参数(如果有)   bean定义。

我从未使用过这种方法,但我认为它适用于您的情况。

修改

这是一个展示我正在谈论的内容的例子(这很简单,但我没有足够的时间写更复杂的内容)。

假设有接口和两个实现:

public interface StringMakerInterface {

    // Just return simple String depending on concrete implementation.
    String returnDummyString();

}

public class StringMakerImpl1 implements StringMakerInterface {

    public String returnDummyString() {
        return "test bean impl 1";
    }


}

public class StringMakerImpl2 implements StringMakerInterface{

    public String returnDummyString() {
        return "test bean impl 2";
    }

}

我们有一个类使用这个接口的具体实现,我们应该在其中注入conctrete实现:

public class StringPrinter {

    private StringMakerInterface stringMaker;

    public StringMakerInterface getStringMaker() {
        return stringMaker;
    }

    public void setStringMaker(StringMakerInterface stringMaker) {
        this.stringMaker = stringMaker;
    }

    public StringPrinter() {

    }

    // Just print dummy string, returned by implementation
    public void printString() {
        System.out.println(stringMaker.returnDummyString());
    }
}

以下是我的示例的配置类:

@Configuration
public class TestFactoryMethodConfig {

    @Bean(name = "stringMaker1")
    public StringMakerImpl1 stringMaker1() {
        return new StringMakerImpl1();
    }

    @Bean(name = "stringMaker2")
    public StringMakerImpl2 stringMaker2() {
        return new StringMakerImpl2();
    }

    @Bean(name = "stringPrinter")
    @Scope(value = "prototype")
    public StringPrinter stringPrinter(@Qualifier("stringMaker1") StringMakerInterface stringMaker) {
        StringPrinter instance = new StringPrinter();
        instance.setStringMaker(stringMaker);

        return instance;
    }
}

这是一个在运行时演示dinamically注入的测试用例:

@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={TestFactoryMethodConfig.class})
public class TestFactoryMethod {

    @Autowired
    private ApplicationContext applicationContext;

    @Resource(name = "stringMaker1")
    private StringMakerInterface stringMaker1;

    @Resource(name = "stringMaker2")
    private StringMakerInterface stringMaker2;

    @Test
    public void testFactoryMethodUsage() {

        StringPrinter stringPrinter1 = (StringPrinter) applicationContext.getBean("stringPrinter", stringMaker1);

        StringPrinter stringPrinter2 = (StringPrinter) applicationContext.getBean("stringPrinter", stringMaker2);

        stringPrinter1.printString();
        stringPrinter2.printString();
    }

}