将属性注入同一个类的不同实例(Spring Framework)

时间:2017-12-15 10:35:25

标签: java spring dependency-injection

“如果需要,请将其标记为重复,但请在评论中留下解决方案链接。”
我有一个类“Assignment22.Player.java”,我必须创建5个实例并为它们注入属性。我可以通过在XML文件本身中对它们进行硬编码来为实例注入属性。但我希望这样做,以便在将来有一些“更改”要求的情况下,我不必转到XML文件来更改属性。这可以使用一个/多个属性文件来实现。
这是我试图做的事情:
我为五个不同的实例创建了五个属性文件。但是,因为,类是相同的,因此每个对象的属性名称将是相同的。所以貌似,我不能以这种方式使用属性文件。
这是我尝试过的xml代码:

  <!-- country bean  -->
  <bean id = "country1" class="Assignmetn22.Country">
    <property name= "countryId" value="${countryId}"></property>
    <property name= "countryName" value="${countryName}"></property>
  </bean>
  <bean id = "country2" class="Assignmetn22.Country">
   <!-- since the properties' names are same there won't any effect if assign them different values 
  and use them for different beans.
   -->
 </bean>


 <bean id = "player1" class="Assignment22.Player">
   <property name="playerId"  value="${playerId}"></property>
   <property name="playerName" value="${playrName}"></property>
   <property name="country" ref="country1"></property>
 </bean>

 <bean id = "player2" class="Assignment22.Player">
   <!-- same properties' names for other bean -->
   <!-- since the properties' names are same there won't any effect if assign them different values 
  and use them for different beans.
   -->
   <!--   <property name="playerId"  value="${playerId}"></property>
          <property name="playerName" value="${playrName}"></property>
          <property name="country" ref="country2"></property>
    -->
  </bean>


  <!--loading the properties file-->
    <bean id= "placeholderConfig1" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <property name="location"  value="classpath:p1.properties"></property>
   </bean>
   <bean id= "placeholderConfig2" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location"  value="classpath:p2.properties"></property>
  </bean>
   <bean id= "placeholderConfig3" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location"  value="classpath:p3.properties"></property>
   </bean>
  <bean id= "placeholderConfig4" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location"  value="classpath:p4.properties"></property>
 </bean>
 <bean id= "placeholderConfig5" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location"  value="classpath:p5.properties"></property>
  </bean>

我需要知道如何动态地将不同的属性值注入相同引用类型(具有相同属性名称)的不同bean。我不想使用XML对它们进行硬编码。有没有java方式?请解释一下。

2 个答案:

答案 0 :(得分:2)

您可以在bean中使用Spring @ Value注释。当创建新实例时,Spring将为您填充属性值。

public class Player
{
     @Value("${playerName}")
     private String playerName;
}

如果您想坚持使用XML配置而不使用注释,请创建一个包含您的属性的bean并将其连接到您的Player-Beans中。

使用范围=&#34;原型&#34;在playerProperties上为每个玩家创建一个实例。这样玩家就不会分享这些属性。

使用范围=&#34;单身&#34; (这是默认设置)让Player实例共享PlayerProperties Bean。

public class Player
{
    PlayerProperties props;
}

public class PlayerProperties
{
    String playerName;
    //getter,setter,...
}


<bean id = "player2" class="Player">
   <property name="props"  ref="playerProperties"></property>
   ...
</bean>


<bean id = "playerProperties" class="PlayerProperties" scope="prototype">
    <property name="playerName" value="${playrName}"></property>
    ...
</bean>

答案 1 :(得分:0)

申请类:

@ComponentScan
@EnableAutoConfiguration
@EnableConfigurationProperties 
@EnableAsync
@EnableScheduling
@Configuration
@SpringBootApplication

//use players.properties
@PropertySource("classpath:players.properties") 
public class InstancePropsApp {

    public static void main(String[] args) {
        SpringApplication.run(InstancePropsApp.class, args);
    }

    //Create 3 Player Beans (could be done in XML-Config, too)
    @Bean Player player1() {return new Player();}
    @Bean Player player2() {return new Player();}
    @Bean Player player3() {return new Player();}

    @PostConstruct
    public void init()
    {
        //Output values after init. 
        player1().echoName();
        player2().echoName();
        player3().echoName();
    }

}

玩家类

@Component
@Scope("prototype")
//Make bean aware of it's name to use bean name as property prefix
public class Player implements BeanNameAware  {

    @Autowired
    private ConfigurableEnvironment environment;

    private String name;


    public void setName(String name) {
        this.name = name;
    }

    private String beanName;

    @PostConstruct
    public void init() {
        //init this beans properties from "beanName.xxx" values. e.g. 
        //player1.name and player2.name ans so on
        new RelaxedDataBinder(this, beanName).bind(new 
        PropertySourcesPropertyValues(environment.getPropertySources()));
    }

    //We use our very own bean name as prefix to load properties per
    //prototype instance
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public void echoName()
    {
        System.out.println(beanName + " : " + name);
    }

}

players.properties:

player1.name=max
player2.name=theo
player3.name=karren

将打印

player1 : max
player2 : theo
player3 : karren