Monday, 1 March 2010

Spring: setting static fields

This is pretty obscure, but I just found this nice trick with Spring framework, for injection of values into static fields: I've been looking for a way to do this for AGES.

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="" xmlns:context="" xmlns:util="" xmlns:xsi="" xmlns="" xsi:schemalocation="

    <!-- Scan for @Autowired annotations -->

    <!-- 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">

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">
                <ref bean="myPrecious"/>

    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.


  1. Nice work. I think there is also another difference when using the MethodInvokingFactoryBean. Where you can use the static method and not have the bean (that has the static method) in the container, the method is just used as initialization.

    Using your beans as example

    If you don't specify and just use the MethodInvokingFactoryBean declaration then since your static setInstance method returns void, there is no bean generated. I used this to initialize a class with just statics that i did not want in the container.

  2. Looks like some of my comment got cut off since i used the xml notation. It should say

    If you don't specify bean class="very.public.api.StaticHub" name="dummyInstanceOfStaticHub" and just use .....

  3. It is NOT working in Spring 3.1.3 . Who ever has it got worked are you using different Spring version than Spring 3.1.3 ..?

  4. The project I was using was on Spring 3.0.0 - haven't tested it with anything else.

  5. Tried with 4.1.6 and it still doesn't work. Although, thanks for the article!

  6. But you are having to create an instance of StaticHub - then what is the point of making the variable static if we had to create an object for it? Its like a hack and is of no real use but academic demonstration . :-(

    1. The benefit: we don't have a public constructor or setter. The "hack" allows us to keep the static API clean.