Jakarta ee 选择要注入而不重新编译的EJB

Jakarta ee 选择要注入而不重新编译的EJB,jakarta-ee,dependency-injection,ejb,Jakarta Ee,Dependency Injection,Ejb,假设您有两个@Local接口的实现 @Local public interface LocalInterface { } @Stateless public class MyFirstImplementation implements LocalInterface { } @Stateless public class MySecondImplementation implements LocalInterface { } 我想选择,而无需重新编译项目(即在运行时或使用外部配置属性),我想

假设您有两个
@Local
接口的实现

@Local
public interface LocalInterface {
}

@Stateless
public class MyFirstImplementation implements LocalInterface {
}

@Stateless
public class MySecondImplementation implements LocalInterface {
}
我想选择,而无需重新编译项目(即在运行时或使用外部配置属性),我想使用哪个项目(MyFirstImplementation或MySecondImplementation)

public class MyClass {
   @EJB
   LocalInterface local;
}

一旦选择了一个实现,它就不必更改。如果有帮助的话,我正在使用JBoss 5.1。

您可以使用部署描述符来实现它-。类似这样的东西(可能不是100%准确,但我认为你已经抓住了要点):


类名
ejb/myLocalReferencedBean
一场
com.yourpackage.LocalInterface
我的第一个实现
地方的
我的第一个实现
mysecondim实现

另一种方法是使用此处描述的CDI:

PedroKowalski概述的方法是一种典型的方法。关于“external configuration property”的另一个技巧是简单地配置构建器,使您生成的保存EJB的jar中只有一个实现


因此,您不必重新编译类或更改任何源代码,但必须重建jar以选择其他实现。

另一种方法是使用JNDI查找EJB引用,而不是依赖自动注入,以防它可以帮助其他任何人:

public class MyClass {
   LocalInterface local;

   @PostConstruct
   public void init() {
       local = findImplementation();
   }

   private LocalInterface findImplementation() {
       try {
            InitialContext context = new InitialContext();
            String ejbPath = // read from an external property
            return (LocalInterface) context.lookup(ejbPath);
       } catch ... { ... }
   }
}

这就是我最后所做的,因为对于JBoss5(@生成的
注释。我标记为已接受,因为如果没有其他限制,CDI注释似乎是更好的解决方案。

谢谢Arjan。这是当前使用的方法,但它不再有效,因为在生产环境中重建jar不是一个选项。谢谢。如果“MyClass”本身不是ejb,则EJBJAR解决方案似乎不起作用,因为根据DTD,必须指定主/远程接口。如果我没有错的话,CDI方法只对JEE6有效。@GuidoGarcía你是对的-MyClass必须是EJB类。CDI解决方案更加灵活,因为您甚至可以将配置放到其他地方,即数据库。此外,无论您在哪里使用
@Inject
,它都可以工作。只是一个小提示:它是一个XML模式,而不是DTD。家庭/远程接口不是必需的-这取决于您使用的EJB版本。不幸的是,
MyClass
存在的战争中的
web.xml
仍然需要提供
声明才能在JNDI树中查找bean。
子元素将在
java:comp/env
下指示EJB的位置。修改
web.xml
显然是构建时的更改。
public class MyClass {
   LocalInterface local;

   @PostConstruct
   public void init() {
       local = findImplementation();
   }

   private LocalInterface findImplementation() {
       try {
            InitialContext context = new InitialContext();
            String ejbPath = // read from an external property
            return (LocalInterface) context.lookup(ejbPath);
       } catch ... { ... }
   }
}