What that article doesn't mention, and the key benefit in my project, is that when you use @AutoWired, you can have the Spring-invoked initialization method marked as private, to avoid polluting your public API.
Spring config:
<beans xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- Scan for @Autowired annotations -->
<context:annotation-config>
<!-- The instance to be injected into the static field on StaticHub -->
<bean class="internal.stuff.MyInterfaceImpl" name="myPrecious">
<!-- The class which will have its static field set via @Autowired -->
<bean class="very.public.api.StaticHub" name="dummyInstanceOfStaticHub">
</beans>Java class with static field:
package very.public.api;
import org.springframework.beans.factory.annotation.Autowired;
public final class StaticHub {
private static MyInterface theStaticInstance;
/**
* Note this initialization method is private! No nasty public setInstance method.
*/
@Autowired(required = true)
private StaticHub(MyInterface instance) {
theStaticInstance = instance;
}
/**
* My public API, making the Spring-created instance of MyInterface statically accessible
*/
public static MyInterface getInstance() {
return theStaticInstance;
}
}This is a big improvement over my previous unsatisfactory solution, which was to use org.springframework.beans.factory.config.MethodInvokingFactoryBean with a public method on StaticHub like this:
<bean name="staticHubInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="very.public.api.StaticHub.setInstance"/>
<property name="arguments">
<list>
<ref bean="myPrecious"/>
</list>
</property>
</bean>
public static void setInstance(MyInterface instance) {
theStaticInstance = instance;
}...which is not very pretty.You can also use @Qualifier to disambiguate if you have multiple beans in your Spring container which implement MyInterface:
import org.springframework.beans.factory.annotation.Qualifier;
...
private StaticHub(@Qualifier("myPrecious") MyInterface instance) {
theStaticInstance = instance;
}Before you use this, consider carefully whether static fields are actually a good idea - in general this kind of pattern is something Spring is designed to help you avoid!
In my project there are good reasons for it, but it needs thought - things get complicated quickly in environments with multiple classloaders, or with multiple Spring containers inside the same classloader; it also makes it harder to use newfangled clustering technologies which let you scale to multiple JVMs.