What is the best way to get a reference to a spring bean in the backend layers?
I have two spring config files and I'm specifying them in my web.xml as in below.
web.xml snippet
..
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/classes/domain-context.xml WEB-INF/classes/client-ws.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
..
From my domain object I have to invoke a Web Service Client and in order to get a reference to the Web Service client I do this:
ApplicationContext context = new ClassPathXmlApplicationContext("client-ws.xml"); //b'cos I don't want to use WebApplicationContextUtils
ProductServiceClient client = (Produc开发者_开发百科tServiceClient) context.getBean("productClient");
..
client.find(prodID); //calls a Web Service
..
However, I have concerns that looking up the client-ws.xml file and getting a reference to the ProductServiceClient bean is not efficient. I thought of getting it using WebApplicationContextUtils. However, I don't want my domain objects to have a dependency on the ServletContext (a web/control layer object) because WebApplicationContextUtils depends on ServletContext. What is the best way to get a reference to a spring bean in the backend layers?
Thanks!
I prefer to inject the Spring container into an applicationContext variable. Spring supports this with the ApplicationContextAware
interface. Then it's easy to ask for a new bean from the code.
An example:
public class ContextAwareFactory implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public String getConfigValue() {
return (String)applicationContext.getBean("config-value");
}
}
Why would you not inject the client into the back end bean? "Don't call us, we'll call you" - objects should be given their dependencies. That's what Spring and DI are all about.
This code:
new ClassPathXmlApplicationContext("client-ws.xml");
will create an entirely new and separate application context to the one defined in your web.xml. Efficiency is one thing but a bigger issue here is correctness.
A bigger issue is that directly calling a bean by name is not really what dependency injection and Spring are all about.
What exactly do you mean by "domain object"? If possible, this object should be made "Spring-aware" and the WS client should be injected by:
explicitly injecting it from the application context (probably not applicable to a domain object but mentioned for completeness);
using
@Autowired
; orusing
@Configurable
.
精彩评论