5

Right now i've application related data in spring bean map and passed this map to other classes as ref.

Map is defined as below

<bean id="sampleMap" class="java.util.HashMap">
    <constructor-arg index="0" type="java.util.Map">
        <map key-type="java.lang.Integer" value-type="java.lang.Float">
            <entry key="1" value="5"/>
            <entry key="2" value="10"/>
            <entry key="3" value="15"/>             
        </map>
    </constructor-arg>
</bean>

This map is referred in other beans as

<bean id="config" class="com.example.Config" abstract="false">      
    <property name="sampleMap" ref="sampleMap"/>
    .
    .
</bean>

I just want to retrieve the map values from database table and want to inject that to other classes. How can i do that in spring. Basically that table contains application related data.The key and values of map will be int,Configuration.

What is the best place to load the configuration data? can we do with spring beans map or is there any other good approach to load configuration from database and refer that in other places of application like service,delegate and DAO?

Help will be appreciated

Thanks

Javee
  • 71
  • 1
  • 1
  • 8

3 Answers3

3

You should use spring's FactoryBean.

public class MyHashMapFactoryBean implements FactoryBean<Map<Integer, Float>>{

  @Autowired
  private Datasource datasource; 

  public Map<Integer, Float> getObject(){
    return <load from database>;
  }

  public Class<Map> getObjectType() { return Map.class ; }

  public boolean isSingleton() { return true; }
}

<bean id="sampleMap" class="my.package.MyHashMapFactoryBean">
  <here you could pass some properties e.g. jdbc datasource>
</bean>
kan
  • 28,279
  • 7
  • 71
  • 101
1

The FactoryBean answer is correct, but it's the old way of doing things.

Instead, use a @Configuration class

@Configuration
public class DBConfiguration{

    @Autowired
    private DataSource dataSource;

    @Bean
    public Map<Integer, Float> configMap(){
        // use dataSource to get map values
    }

}

One of the many advantages to this approach is that you can autowire the DataSource into the configuration class.

BTW, using a map as bean doesn't feel right. I'd create a wrapper object around the map and use that as Spring Bean, but opinions differ on that.

Community
  • 1
  • 1
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • A factory bean could be autowired too. But yes, nice to know another way. – kan Feb 05 '13 at 15:59
  • @kan yes, you can autowire the FactoryBean itself, but not the Bean it creates. The FactoryBean has to manually construct that Bean. With `@Configuration`, and `@Bean(autowire=BY_NAME)` (or `BY_TYPE`) you get full autowiring of the bean object you create in your method. – Sean Patrick Floyd Feb 05 '13 at 18:46
  • Oh, right. I didn't thought that he may need to autowire a Map. But in old fashion way it is possible with ApplicationContextAware interface. – kan Feb 05 '13 at 18:51
  • @kan as I wrote, I don't think he should use a map as bean in the first place. and `ApplicationContextAware` will only let you autowire the bean programmatically through `applicationContext.getAutowireCapableBeanFactory().autowireBean()` which is a lot more code than an annotation parameter. But why argue with me, it's the Spring developers themselves who suggest to use `@Configuration` over `FactoryBean` in the above article. – Sean Patrick Floyd Feb 05 '13 at 19:07
  • Strictly speaking if he would use a new class instead of the Map, he doesn't need a factory. The class itself could do the loading. Anyway, yes, Spring 3.1 has nice features. – kan Feb 05 '13 at 22:55
0

what i actually found out today, is that when you need map of bean names to instances of specific interface, there is no need of @Qualifier's and any sort of FactoryBean code. Spring would find and inject candidates for you. Little bit of magic, but it seems to work that way.

nefo_x
  • 3,050
  • 4
  • 27
  • 40