所以经过一些研究,我似乎有两种方法可以在 Guice/RPC Dispatch 应用程序中使用 EJB 注入:
1。集中注入
EJB 注入在GuiceServletContextListener 或任何您的子类的名称中工作。在那里你可以例如通过@EJB注解注入一个bean,然后在getInjector()方法中将引用传递给一个模块:
import javax.ejb.EJB;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
public class GuiceServletConfig extends GuiceServletContextListener {
@EJB
private SampleBeanLocal sampleBean;
@Override
protected Injector getInjector() {
return Guice.createInjector(new ServerModule(), new BeanModule(sampleBean));
}
}
2。自定义注释
另一种方法是创建一个自定义注释,然后您可以使用它在不可能的地方注入 bean。该实现已被描述为here。
由于代码示例中的一些缺陷,我还将在这里发布我的解决方案:
注释
@Retention(RetentionPolicy.RUNTIME)
@Target({ TYPE, METHOD, FIELD})
public @interface GuiceEJB {
/**
* Name of the bean.
*
* @return Name of the bean.
*/
String name();
/**
* Local EJB as default type.
*
* @return bean type.
*/
String type() default "local";
}
类型监听器
import java.lang.reflect.Field;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
/**
* Custom Guice {@link TypeListener} for the {@link GuiceEJB} annotation.
*/
public class GuiceEJBTypeListener implements TypeListener {
@Override
public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> encounter) {
Class< ? > clazz = typeLiteral.getRawType();
while (clazz != null) {
// iterate through the fields of the class
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(GuiceEJB.class)) {
encounter.register(new GuiceEJBMemberInjector<I>(field));
}
}
// repeat for super class
clazz = clazz.getSuperclass();
}
}
}
MembersInjector
import java.lang.reflect.Field;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.google.inject.MembersInjector;
/**
* Custom member injector for {@link GuiceEJB} annotations.
*/
public class GuiceEJBMemberInjector<T> implements MembersInjector<T> {
/**
* Field that needs injection.
*/
private Field field;
/**
* Bean type.
*/
private String type;
/**
* Bean name.
*/
private String name;
/**
* @param field
*/
public GuiceEJBMemberInjector(Field field) {
this.field = field;
GuiceEJB annotation = field.getAnnotation(GuiceEJB.class);
this.type = annotation.type();
this.name = annotation.name();
this.field.setAccessible(true);
}
@Override
public void injectMembers(T t) {
try {
if ("local".compareToIgnoreCase(this.type) == 0) {
this.field.set(t, findLocalEJB());
}
} catch (Exception e) {
throw new GuiceEJBInjectException(e);
}
}
/**
* Lookup an local EJB for the given field.
*
* @return
*/
private Object findLocalEJB() {
Context initialContext = null;
Object localRef = null;
try {
// look up the bean by name
localRef = InitialContext.doLookup(this.name);
} catch (Exception e) {
throw new GuiceEJBInjectException(e);
} finally {
try {
if (initialContext != null)
initialContext.close();
} catch (Exception e) {
}
}
return localRef;
}
}