读书人

Using Spring with EJB 三

发布时间: 2012-10-08 19:54:56 作者: rapoo

Using Spring with EJB 3
Using Spring with EJB 3

By Robert. Filed in Java? | ?
Tags: ejb, ioc, spring

?Using Spring with EJB 三Using Spring with EJB 三

Back when we were planning the migration to Glassfish, I realised wewould have two dependency-injection frameworks in use EJB 3 andSpring. For obvious reasons, I wanted to know more about how thesewould interact. At the time (last July), I couldn’t find anyone who hadused EJB 3 and Spring together even Ben Alexfrom Interface21 hadn’t come across it. Six months later, and I stillhaven’t heard of anyone using Spring _from_ EJBs. Except for us.


There’s lots of reasons to use both EJB 3 and Spring. EJBs havebenefits Spring doesn’t give integration with things like Servletsand JSP tags, better integration with the container for monitoring andmanagement, tool support, and so on. Spring has benefits as well mostnotably, you don’t need the container, but also you get more controlover the bean lifecycle. Together, they are a good complement.

But how do you get a Spring-managed bean from an EJB? The answer:dependency injection, of course. That is, with the aid of a EJBInterceptor:

[source='java']
public class SpringBeanInterceptor {

private BeanFactory beanFactory;

@PostConstruct public void configureSpringBeans(InvocationContext context) throws Exception {
for (Method method : context.getTarget().getClass().getMethods()) {
if (method.isAnnotationPresent(SpringBean.class)) {
Class springClass = method.getParameterTypes()[0];
String springName = determineSpringBeanName(method, springClass);
Object springBean = beanFactory().getBean(springName);
try {
method.invoke(context.getTarget(), springBean);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getCause());
}
}
}
context.proceed();
}

private String determineSpringBeanName(Method method, Class springClass) {
String springName = method.getAnnotation(SpringBean.class).value();
if (springName.length() > 0) {
springName = toCamelCase(springClass.getSimpleName());
}
return springName;
}

private String toCamelCase(String string) {
return Character.toLowerCase(string.charAt(0)) + string.substring(1, string.length());
}

private BeanFactory beanFactory() {
if (beanFactory == null) {
BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(”classpath*:beanRefContext.xml”);
BeanFactoryReference ref = locator.useBeanFactory(”applicationContext-service”);
beanFactory = ref.getFactory();
}
return beanFactory;
}
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SpringBean {
String value() default “”;
}
[/source]

That’s it. This Interceptor will look over an EJB, after it’screated, and provides the Spring beans. This version looks for’setter-methods’ with an @SpringBean annotation (youcould also change it to look for fields), and looks up a correspondingbean from the Spring context (the ContextSingletonBeanFactoryLocatormakes this possible).

Here’s how you would use it:

[source='java']
@Stateless
@Interceptors(SpringBeanInterceptor.class)
public class MyServiceBean implements MyService {
private MySpringBean bean;

@SpringBean public void setMySpringBean(MySpringBean bean) {
this.bean = bean;
}
}
[/source]

With this (and one other trick I’ll discuss soon), you can (nearly) seamless integrate EJB3 and Spring.

The one big limitation of this: with Stateless Session Beans, youcan only inject stateless dependencies, and you can only inject themwhen the EJB is initialised.

读书人网 >软件架构设计

热点推荐