I will give you two alternatives. The first one are currently in a production environment. The second alternative is something that I came up with after thinking about this problem once more.
Still, this should be avoided, but if you have code that currently does not know about Spring, this can be used.
Alternative 1
Implement ApplicationContextAware
I had a situation where we needed to autowire a static field. I am working with legacy code where we want to use spring and jpa (hibernate) in our new code. In general it is bad practice to autowire static fields, but I belive that it can be motivated when considering the greater good for the application.
We solved this situation by implementing ApplicationContextAware. Se blelow:
public class DbHandler implements ApplicationContextAware {
private static DataSource dataSource;
protected DbHandler(){
//Needs to be protected (not private) for Spring
}
//This method is used in many places in the code, and we can not change how it is
//used. We wanted to use a datasource from Spring
public static Connection getConnection() throws java.sql.SQLException {
return dataSource.getConnection();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
DbHandler.dataSource = applicationContext.getBean("dataSource", javax.sql.DataSource.class);
}
}
And since the class is not in a package that is scanned by spring we added it to the context.xml
<bean id="dbHandler" class="se.ucr.db.DbHandler" depends-on="dataSource"/>
This is not as easy as easy as writing @Autowired, but it works.
Alternative 2
Create a singelton
A bean that can be injected:
@Component
public class BeanToInject {
private static final Logger LOGGER = LoggerFactory.getLogger(BeanToInject.class);
public String getValue() {
return "Value from SpringBean";
}
}
A simple Singelton that will inject the bean that is defined above:
public class NeedStaticFieldInjected {
private static final Logger LOGGER = LoggerFactory.getLogger(NeedStaticFieldInjected.class);
private static NeedStaticFieldInjected INSTANCE;
private NeedStaticFieldInjected() {
//private constructor
}
@Autowired
private BeanToInject beanToInject;
public static NeedStaticFieldInjected getInstance() {
if (INSTANCE == null) {
INSTANCE = new NeedStaticFieldInjected();
}
return INSTANCE;
}
public static String getValueFromSpringBean() {
if (INSTANCE.beanToInject == null)
return "Not initialized correctly";
return INSTANCE.beanToInject.getValue();
}
}
And finally, the spring-context:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.emancipering.components"/>
<bean id="needStaticFieldInjected" class="org.emancipering.components.NeedStaticFieldInjected" factory-method="getInstance" />
</beans>
You will access the autowired properties via the static variable INSTANCE
, as shown in NeedStaticFieldInjected .getValueFromSpringBean()
. This is very close to the aim of injecting a static field. Of course, it is possible to have many more Autowired properties, but I just added one in this example.
It is important that factory-method="getInstance"
is specified, otherwise this will fail.
I hope this is useful for someone.