如何在Spring中的运行时设置bean限定符名称

时间:2014-08-31 08:55:57

标签: java spring java-ee dependency-injection

我们可以为bean设置限定符名称(例如@Qualifier(value="myBeanQualifiedName"))。但我想知道如何在@Configuration课程中的运行时设置限定符名称。

假设基于应用程序逻辑,我想给bean一个名称作为配置文件中的限定符 的编辑:

ConcreteBean是MyAbstractBean的子类。

@Configuration
public class MyBeanFactory {

    @Bean
    public MyAbstractBean getMySpecifiedBean(String condition){
        String QUALIFIER_NAME="QulifierName"+condition;
        if(//some condition here ){
        //How to set a qualifier name :QUALIFIER_NAME for this ConcreteBean instance?    
       MyAbstractBean b1= new ConcreteBean();
       b1.setService(new AnotherService1);  // and set some field values to this concrete bean
       return b1;
        }
        else  {
         MyAbstractBean b2= new ConcreteBean();
       b2.setService(new AnotherService2);  
       return b2;
        }

    }
}   

假设从不同位置调用 getMySpecifiedBean()方法,并且每个位置都需要差异实例,但需要ConcretBean()的类型。由于setService()方法设置了不同的属性值,因此实例彼此不同。因此,b1和b2将与使用它们的服务实例做不同的事情。

在上面的示例中,根据条件,QUALIFIER_NAME名称将被更改。那么我们是否可以将准备好的QUALIFIER_NAME分配给新创建的bean的限定符名称?以及如何使用限定符名称获取此类bean(限定符名称已知)?例如,在另一个位置,
String qalifierName =" QulifierName" + preparedConditionedString; @Autowired @Qualified(qalifierName)

String qalifierName2 =" QulifierName" + preparedConditionedString2;
@Autowired @Qualified(qalifierName2)

你也可以想一想,如果我们对限定符进行硬编码,那么想想如果要创建20个或更多个实例呢?我们必须重复这些代码。

1 个答案:

答案 0 :(得分:3)

扩展我的"看看ServiceLocatorFactoryBean"评价:

public class MyBeanFactory
{
    private IServiceFactory serviceFactory;
    private IDecisionMaker decisionMaker;

    public IBean createNewInstance(final String condition)
    {
      String conditionResult = decisionMaker.decide(condition);
      return serviceFactory.getNewInstance(conditionResult);
    }

    public void setServiceFactory(final IServiceFactory serviceFactory)
    {
        this.serviceFactory = serviceFactory;
    }
    public void setDecisionMaker(final IDecisionMaker decisionMaker)
    {
        this.decisionMaker = decisionMaker;
    }
}

IServiceFactory界面 这将允许您将原型bean映射到决策字符串(您的问题的核心功能)。

public interface IServiceFactory
{
    IBean getNewInstance(String identifier);
}

IBean界面 这将允许您从工厂处理返回的bean(原型)。

public interface IBean
{
    //TODO
}

IDecisionMaker界面。 这将使您的决策制定流程不受工厂代码的限制。 实现采用您的condition字符串并返回一个属性名称,该名称将从IServiceFactory实现/配置中生成一个IBean。

public interface IDecisionMaker
{
    String decide(String condition);
}

Spring xml Konfiguration

<! implementations of the IBean interface -->
<bean id="myBeanRed" class="..." scope="prototype" />
<bean id="myBeanBlue"  class="..." scope="prototype" />
<bean id="myBeanGreen" class="..." scope="prototype" />

<!-- the decision maker -->
<bean id="decisionMaker" class="...">
       <!-- define your decision making here  like:
            condition(color=red)->red
            condition(color=blue)->blue
            condition(ELSE)->green
        -->
</bean>

<!-- the abstract factory -->
<bean id="myBeanServiceFactory" class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
    <property name="serviceLocatorInterface" value="...IServiceFactory "/>
    <property name="serviceMappings">
        <props>
            <prop key="red">myBeanRed</prop>
            <prop key="blue">myBeanBlue</prop>
            <prop key="green">myBeanGreen</prop>
        </props>
    </property>
</bean>

<!-- the factory -->
<bean id="myBeanFac" class="...MyBeanFactory" scope="singleton">
    <property name="serviceFactory" ref="myBeanServiceFactory" />
    <property name="decisionMaker" ref="decisionMaker" />
</bean>