Automatically collecting objects of a given type with Spring
During a recent presentation on Spring, or more precisely its IoC container, at HP, I showed an example that several colleagues had asked me about independently. I am sharing it today. The problem was this. We have objects that implement a particular interface. We also have a registry object that we want all those objects to register with automatically. Of course, we do not know in advance how many there will be at runtime.
Spring lends a hand with a feature called autowiring. Autowiring lets the IoC container resolve object dependencies automatically without our explicitly specifying which dependencies to use. Instead, we tell the container that the dependency must meet certain criteria. Here, we say “all objects of the given type.” You can control autowiring with annotations, where it is the default, or with XML. The example uses annotations.
Interface
package com.hp.systinet.springioc.beancollector;
public interface BusinessService {
}
Implementation A
package com.hp.systinet.springioc.beancollector;
import org.springframework.stereotype.Service;
@Service("serviceA")
public class BusinessServiceA implements BusinessService {
}
Implementation B
package com.hp.systinet.springioc.beancollector;
import org.springframework.stereotype.Service;
@Service("serviceB")
public class BusinessServiceB implements BusinessService {
}
The registry itself
01 package com.hp.systinet.springioc.beancollector;
02
03 import java.util.List;
04 import java.util.Map;
05
06 import org.springframework.beans.factory.annotation.Autowired;
07 import org.springframework.stereotype.Component;
08
09 @Component
10 public class ServiceRegistry {
11 @Autowired
12 private List services;
13
14 @Autowired
15 private Map servicesByName; //a bean name is the key
16
17 public BusinessService getServiceByName(String name) {
18 return servicesByName.get(name);
19 }
20
21 public int count() {
22 return services.size();
23 }
24 }
If you are used to declaring beans in XML, the meaning of the annotations may be unclear. The @Component annotation marks an object as a managed bean. The @Service annotation is a specialization that indicates the component represents application logic. Future versions of Spring may extend the treatment of @Service. The optional annotation argument supplies the managed bean's name.
The @Autowired annotation on lines 11 and 14 tells the container to inject a dependency of type BusinessService. Used this way, the annotation requires at least one managed bean implementing the interface. If that behavior does not suit you, the annotation's required parameter lets you turn it off.
The bulk collection behavior is expressed by using either Map or List as the variable type. With either type, the IoC container fills it with all the managed beans of type BusinessService. In a Map, it also uses each bean's name as the key, in our case serviceA and serviceB.
Related articles
Related CZ Podcast episodes
- #3 · Java 6 SE, Vývoj webových aplikací
Dagi and Filemon discuss Java 6 and web application frameworks. · Czech audio
- #1 · Vývojová prostředí v Javě
The first CZ Podcast episode looks at Java development environments. · Czech audio