Inject Spring beans into EJB3
I'm trying to inject Spring beans into an EJB using @Interceptors(SpringBeanAutowiringInterceptor.class)
but I cannot get it working with the beanRefContext.xml
examples I've seen.
Here's my EJB:
@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class AlertNotificationMethodServiceImpl implements
AlertNotificationMethodService {
@Autowired
private SomeBean bean;
}
I've provided a beanRefContext.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="...">
<!-- Have also tried with ClassPathXmlApplicationContext -->
<bean id="context"
class="org.springframework.web.context.support.XmlWebApplicationContext">
<property name="configLocations" value="/config/app-confi开发者_如何转开发g.xml" />
</bean>
</beans>
But, it seems to be recreating the beans instead of obtaining the existing ApplicationContext. I end up with the following exception because one of my beans is ServletContextAware.
java.lang.IllegalArgumentException: Cannot resolve ServletContextResource
without ServletContext
When using the SpringBeanAutowiringInterceptor
, shouldn't it obtain the ApplicationContext instead of create a new one?
I also tried changing my web.xml so the contextConfigLocation points to the beanRefContext.xml, hoping it'd load my Spring config but I end up with the same exception as above.
Does anyone know how to do this properly? The examples I've seen seem to use the same method I'm using which I assume means the beans are being recreated when the Interceptor is invoked (or is that how it's supposed to work and I've misunderstood).
When using the
SpringBeanAutowiringInterceptor
, shouldn't it obtain theApplicationContext
instead of create a new one?
Yes, and this is in fact what it does. It uses the ContextSingletonBeanFactoryLocator
mechanism, which in turn manages a number of ApplicationContext
instances as static singletons (yes, even Spring has to resort to static singletons sometimes). These contexts are defined in beanRefContext.xml
.
Your confusion seems to stem from the expectation that these contexts have any relation to your webapp's ApplicationContext
- they don't, they're entirely separate. So your webapp's ContextLoader
is creating and managing a context based on the bean definitions in app-config.xml
, and the ContextSingletonBeanFactoryLocator
creates another one. They won't communicate unless you tell them to. The EJBs cannot get hold of the webapp's context, since EJBs sit outside of that scope.
What you need to do is to move the beans that need to be used by your EJBs out of app-config.xml
and into another bean definition file. This extracted set of bean definitions will form the basis of a new ApplicationContext
which will (a) be accessed by the EJBs, and (b) will act as the parent context of your webapp's context.
In order to activate the parent-child link between your webapp's context and the new context, you need to add an additional <context-param>
to your web.xml
called parentContextKey
. The value of this parameter should be the name of the context defined in beanRefContext.xml
(i.e. context
, in your example).
The beans that stay behind in the webapp's context will be able to reference the beans in the parent context, as will the EJBs. However, the EJBs will not be able to reference anything in the webapp's context.
Also, you cannot use XmlWebApplicationContext
in beanRefContext.xml
, since that class requires awareness of the webapp, and ContextSingletonBeanFactoryLocator
cannot supply that awareness. You should stick with ClassPathXmlApplicationContext
there.
精彩评论