Spring annotations static injection tutorial
Wednesday, February 11th, 2009 - 1:19 pm - Spring
Spring’s architecture isn’t very friendly to static classes and methods. It doesn’t have any way of injecting static properties of classes because it doesn’t have any way to discover them. Spring’s designers have acknowledged that it’s a shortcoming of the framework and suggest the use of this solution.
- Create the static property of the class without any annotations
- Mark the class to have static properties injected with @Component so that the properties will be injected on Spring startup
- Create a non-static setter method that sets the static property
- Mark the setter method with @Autowired(required = true)
@Component
public class UserUtils
{
private static UserAccessor userAccessor;
/**
* Sets the user DAO. This method should never be called except by Spring
* @param userAccessor The user accessor to set
*/
@Autowired(required = true)
public void setUserAccessor(userAccessor UserAccessor) {
UserUtils.userAccessor = userAccessor;
}
}
Using this technique, you can have all of the advantages of Spring injection without the headaches of Spring injection! Avoid using this technique whenever possible. It should only be used to support legacy applications. With a lot of statically stored values, your application will not scale well.
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 ..?
Thank you! It works
[…] – http://planproof-fool.blogspot.com/2010/03/spring-setting-static-fields.html – http://www.connorgarvey.com/blog/?p=105 – […]
Nice solution to my problem. I am doing some quick and dirty bench mark testing leveraging Junit and SpringJunit4ClassRunner. My problem was that I needed a way to kill Hazelcast before it was automatically starting again by Spring in the next test class.
Again nice solution…. I tend to forget the little gold nuggets as time goes on (day-to-day).
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@Component
public class WriteBehindCrudTest extends AbstractThreadedCrudTest {
private static HazelcastInstance instance;
@AfterClass
public static void after(){
instance.getLifecycleService().kill();
}
@Autowired(required = true)
public void setInstance(HazelcastInstance instance){
WriteBehindCrudTest.instance = instance;
}
}
I agree with MattL, except that the author here is specified that its for situations where you have legacy code and it is true tha a lot of legacy code ‘l time’ used a lot of static variables and stuff.
However, I’d be inclined to push code into places like a method with @PostConstruct annotation. This would mean the bean is fully initialized with all dependencies and now you can initialize the static member common to all instances (singleton or not).
Note:: If the static variable value is not common for all instances, then its WRONG to be static by definition anyway.
Nice Solution. Having static methods is one usage of having static field injection.
Though I didn’t understand why Spring does not encourage static field inject and how do static values affect the scale factor of an application. It would be helpful if someone could detail out on this a bit.
Thanks, helped me to solve my problem!
Better solution would be:
@Component
public class UserUtils
{
private static UserAccessor userAccessor;
@Autowired(required = true)
public UserUtils(@Qualifier(“userAccessorImpl”) userAccessor UserAccessor) {
UserUtils.userAccessor = userAccessor;
}
}
The problem with this approach is that the setter injection of a non-static variable can happen AFTER the static variable has already been used. So, beans that use the static variable before it has been initialized by the non-static setter will get the default value of the property while beans that use the property later will get the initialized value. So, this is not a perfect solution.
@MattL, hi man, personally i use static constants as a key for both sessions and Context in generals, the point is accesibility, a public static variable it is accessible everywhere, whereas singleton object handle by spring appcontext means that you have a reference of that context.
for sure there are some reason why spring arch. did not develop the support for this point anyway a workaround always exist.
Nice hint, added to bookmarks 😉 However, it doesn’t work with JUnit 4 test cases, where I wanted to inject a resource used for initializing another field in @BeforeClass which has to be static.
@MattL: static definitely isn’t about changes, so I’m not sure, whether your rule makes any sense…
I always considered Spring’s lack of static injection a feature.
The semantics of static properties and especially singletons are often not fully understood and can result in very obscure problems and assumptions. This is especially true when serialization, persistence and remoting are involved.
My rule is: never use static properties unless their value is guaranteed never to change ever for the life of the universe.
Spring has a better option – define an object to be a singleton within some context e.g. the application context. Then we can tidy up the semantics for persistence and clustering and not use statics.
Just my 2c.