Shockingly powerful Spring 2.5 multiple auto-wiring feature

July 2, 2008 at 10:05 pm (Uncategorized) ()

One functionality that I always felt was missing from Spring 2.0 and earlier was the ability to easily quantify over the components in your application.  For instance, I often want some piece of code to have knowledge of every servlet in my application, or every repository, e.g. to monitor them for component management purposes.  This could be hacked in earlier versions of Spring, but only at the cost of making some of your components dependent on the Spring container, or by using some fairly hairy aspect-oriented trickery.  In Spring 2.5, quantification over components becomes much easier, using the new @Autowired annotation, applied to Collection or array-typed setters.

Here, have some example code:


public interface Rule{…}

@Component
public class Rule1 implements Rule {

}

@Component

public class Rule2 implements Rule {



}

@Component
public class RuleEngine {
private Set<Rule> rules;

@Autowired
public void setRules(Set<Rule> rules) {
this.rules = rules;
}
}

In this case, Rule1 and Rule2 are some random rules, and are instantiated automatically via Spring 2.5’s component package-scanning functionality.  RuleEngine is also instantiated by package-scanning, and then injected with the set of all Rule components that are in the application context.  At injection time, ruleEngine.setRules() gets called with a Set containing Rule1 and Rule2, which it can then use for whatever nefarious rule-engine purposes it may require.  Note that there are no references to Rule1 or Rule2 anywhere in either the Java code or the Spring configuration.  It’s tough to get much more loosely-coupled than that.

To add a new rule, just create a new class which fulfills the Rule interface, is annotated as a  @Component, and lives in a package that Spring has been instructed to scan for components. The new rule class need not even be shipped in the same jar as the the RuleEngine component or Spring configuration file.  Anywhere in the classpath is fine.   This is weaker than the hot-swapping functionality provided by various application servers and OSGi containers, but does at least allow for separate builds of core components and the “plug-in” components which get automatically injected into them.

Spring 2.5 offers several possibilites for tweaking this plugin behaviour, such as only injecting some annotated subset of your plugin classes.  For instance, here’s a rule engine that only knows about those rules marked as “High Security”

@Component
public class HighSecurityRuleEngine {
private Set<Rule> rules;

@Autowired
public void setRules(@HighSecurity Set<Rule> rules) {
this.rules = rules;
}
}

where @HighSecurity is an annotation declared as

@Qualifier
public @interface HighSecurity {}

But frankly, that’s just gravy.  Just being able to quantify over components using collection-based auto-wiring and interface filtering is more than adequate for my uses.

Leave a comment