简体   繁体   English

Spring:如何从单个模板定义动态创建多个bean

[英]Spring: how to dynamically create multiple beans from single template definition

I have the following Spring bean for a remote web service defined in xml: 我有以下用于在xml中定义的远程Web服务的Spring bean:

    <bean id="authWSTemplate" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean" abstract="true">
       <property name="serviceInterface" value="com.example.webservices.Authentication" />
       <property name="wsdlDocumentUrl" value="${ws.root}/authentication?wsdl" />
       <property name="namespaceUri" value="http://security.webservices.example.com/" />
       <property name="serviceName" value="AuthenticationWebService" />
       <property name="portName" value="AuthenticationPort" />
       <property name="maintainSession" value="true" />
    </bean>

How do I obtain this bean template and create a concrete bean (ie supply the root property)? 如何获得该bean模板并创建一个具体的bean(即提供root属性)? Can I then put the concrete bean into the Spring container? 然后可以将混凝土豆放入Spring容器中吗?

I need numerous concrete beans pointing to different systems, so I have different root values. 我需要大量指向不同系统的具体bean,因此我具有不同的根值。 For this example, say there are 2 systems with roots: http://domain1.com:8001/ws and http://domain2.com:8002/ws . 对于此示例,假设有两个具有根目录的系统: http : //domain1.com : 8001/wshttp://domain2.com:8002/ws

Therefore I'd want 2 beans called "authWSdom1" and "authWSdom2". 因此,我想要2个名为“ authWSdom1”和“ authWSdom2”的bean。

I'm expecting to do this programmatically in an application initialisation block, where I'd retrieve a list of all known system implementations (this info is only known at runtime), and create a bean for each impl, cache the bean name, then my application will retrieve the appropriate bean from the Spring container when required. 我希望在应用程序初始化块中以编程方式进行此操作,在该程序块中,我将检索所有已知系统实现的列表(此信息仅在运行时才知道),并为每个impl创建一个bean,缓存bean名称,然后我的应用程序将在需要时从Spring容器中检索适当的bean。

Or, is there a better pattern for this? 还是为此有更好的模式? Perhaps by providing the root value in a constructor for the bean? 也许通过在bean的构造函数中提供根值?

I'm thinking I cannot have a single bean in Spring as I need to support concurrent access across multiple end points (ie multiple users hitting domain1 and domain2 at the same time). 我想我在Spring中不能有一个bean,因为我需要支持跨多个端点的并发访问(即,多个用户同时访问domain1和domain2)。

Create custom bean that implements BeanFactoryPostProcessor and InitializingBean. 创建实现BeanFactoryPostProcessor和InitializingBean的自定义bean。 Use postProcessBeanFactory method to create bean: 使用postProcessBeanFactory方法创建bean:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    String wsdlDocumentUrl = ....;
    // .......
    registry.registerBeanDefinition(YOUR_BEAN_NAME, BeanDefinitionBuilder.childBeanDefinition(
                getParentNoDomainServicBeanName(authWSTemplate)).addPropertyReference(
                "wsdlDocumentUrl", wsdlDocumentUrl).getBeanDefinition());

}

While I believe that Ragnor's answer is suitable if you want to dynamically create the bean in the spring container, I decided to use spring to define my own WSTemplate DTO then use a factory class to use this DTO and programmatically build (root url provided at runtime and DTO suffix value added to it) and cache the resulting JaxWS ProxyBean: 虽然我相信Ragnor的答案很适合在弹簧容器中动态创建bean的情况,但我还是决定使用spring来定义自己的WSTemplate DTO,然后使用工厂类来使用此DTO并以编程方式进行构建(运行时提供的根URL)并添加DTO后缀值)并缓存生成的JaxWS ProxyBean:

<bean id="authWSTemplate" class="com.example.WSProxyTemplate">
   <property name="serviceInterface" value="com.example.webservices.Authentication" />
   <property name="wsdlDocumentUrlSuffix" value="/authentication?wsdl" />
   <property name="namespaceUri" value="http://security.webservices.example.com/" />
   <property name="serviceName" value="AuthenticationWebService" />
   <property name="portName" value="AuthenticationPort" />
   <property name="maintainSession" value="true" />
</bean>

I like this approach as my spring config is abstracted away from the actual WS bean used. 我喜欢这种方法,因为我的spring配置是从实际使用的WS bean中抽象出来的。 Ie if I wanted to use something other that JaxWS, then I'd simply write a different factory which used the same DTO beans. 即,如果我想使用JaxWS之外的其他东西,那么我只是写了一个使用相同DTO bean的不同工厂。 Again, this would help if I have to choose the WS implementation at runtime depending upon some system/env criteria. 同样,如果我必须根据某些系统/环境标准在运行时选择WS实现,这将有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM