如何将无接口、外部库 类 注入 JavaEE 应用程序?
How to Inject no interface, external library classes into JavaEE application?
我对 JavaEE 和依赖注入的概念还很陌生。不过我对它还是有一定了解的,虽然我不知道它的所有使用方法。
我的本地界面如下:
@Local
public interface MyInterfaceLocal {
SomeType getMeSometype();
}
实现该接口的class是stateless EJB
@Stateless
public class MyInterfaceImpl {
public SomeType getMeSomeType() {
//Some implementation details...
ExternalLibraryClass externalLib = new ExternalLibrary(arg1, arg2);
return externalLib.externalLibMethod();
}
}
现在的问题是,如何避免实例化 externalLib
并让它以某种方式注入?例如,如果这是我用接口创建的另一个 EJB,那么我可以简单地让 EJB 容器处理实例化,使用如下所示的 @EJB
注释。
@Stateless
public class MyInterfaceImpl {
@EJB
AnotherInterface anotherInterfaceImpl;
public SomeOtherType getMeSomeType() {
//Some implementation details...
return anotherInterfaceImpl.someMethod();
}
}
我希望能够为我正在使用的外部库做(类似的事情),因为这允许我:
- 更改当前正在使用的底层外部库,对我的代码库进行最小的更改。如果需要的话,可能会换成更好的。
- 当我想对
MyInterfaceImpl
class. 进行单元测试时,轻松注入模拟
到目前为止我看过-
创建一个包装器方法,其参数为ExternalLibrary
,因此可以执行某种手动方法参数注入。这仍然使我的实现与底层库紧密耦合。 (或者我做的不对)
使用Context & Dependency Injection
容器进行注入(就像EJB 容器那样做。我知道它不一样)。研究了使用 Producers
的能力。尽管我了解 Producers
对 CDI 的作用,但我无法理解如何利用它?或者即使我走在正确的道路上?
更新:
我找到了几篇帮助我更好地理解 CDI Producers 的文章,我尝试采用这种方法,但遇到了另一个问题。所以现在我有:
ExternalLibraryProducer.java
public class ExternalLibraryProducer {
@Produces
private ExternalLibraryClass1 extrnalLibraryClassProducer() {
return new ExternalLibraryClass1("SomeString", 7);
//The constructor actually takes a string and another commplex type
//as parameters. I am keeping it a little simple here.
//I am trying to set the ExternalLibraryClass1() arguments
//programmatically at runtime.
}
}
现在,我要生成的对象的构造函数接收参数,比方说字符串和整数。我想我可以创建一个 Qualifier
来传递这些参数来生成我想要的对象。
ExternalLibraryClass1Qualifier.java
@Qualifier
@Retention(RUNTIME)
@Target({METHOD})
public @interface ExternalLibraryClass1Qualifier {
String argument1();
Int argyment2(); //This is actually another complex type. Keeping it
//simple here.
}
现在我想做的是,我希望在运行时以编程方式设置参数值(假设来自属性文件)。而且我不知道该怎么做。所以我的最终注射如下所示。
@Stateless
public class MyInterfaceImpl {
@Inject
@ExternalLibraryClass1Qualifier(argument1 = "something", argument2 = 7)
ExternalLibrary externalLib;
public SomeType getMeSomeType() {
//Some implementation details...
return externalLib.externalLibMethod();
}
}
感谢您的指导。
您可以让 ExternalLibrary
的生产者方法接受创建对象所需的参数,并且可以通过 CDI 生产者生成这些参数。
public class ExternalLibraryProducer {
private String name;
private int age;
public ExternalLibraryProducer() {
// set name and age from properties file or elsewhere
// or you can set them individually on their respective producer methods, but might be costly considering you need to read the properties file twice
}
@Produces
public String name() {
return name;
}
@Produces
public int age() {
return age;
}
....
@Produces
private ExternalLibraryClass1 extrnalLibraryClassProducer(String name, int age) {
// Or you can use them directly here, if you opt to not separate this config from the dependencies
return new ExternalLibraryClass1(argument, age);
}
}
CDI 生产者是一种方法,唯一的问题是,您究竟想如何构建它们。
既然你说参数来自 属性 文件,我建议你反转方法并让生产者方法检查 属性 文件并提取值(或询问任何 "reader" 之前这样做并缓存它):
@Produces
private ExternalLibraryClass1 produceExternalLibraryInstance() {
// read the properties from the file or from any cache you use
String arg1 = PropertyReader.getarg1();
Integer arg2 = PropertyReader.getArg2();
// create object with those args
return new ExternalLibraryClass1(arg1, arg2);
}
有了这个你显然不需要限定符然后可以简单地做 @Inject ExternalLibraryClass1
.
请注意,当您创建注入 ExternalLibraryClass1
的对象时,将调用生产者 - 确保您可以尽快从 属性 文件中获取参数。 (当 produces 读取时应该不会有问题,如果你有一些缓存可能会更棘手)
我对 JavaEE 和依赖注入的概念还很陌生。不过我对它还是有一定了解的,虽然我不知道它的所有使用方法。
我的本地界面如下:
@Local
public interface MyInterfaceLocal {
SomeType getMeSometype();
}
实现该接口的class是stateless EJB
@Stateless
public class MyInterfaceImpl {
public SomeType getMeSomeType() {
//Some implementation details...
ExternalLibraryClass externalLib = new ExternalLibrary(arg1, arg2);
return externalLib.externalLibMethod();
}
}
现在的问题是,如何避免实例化 externalLib
并让它以某种方式注入?例如,如果这是我用接口创建的另一个 EJB,那么我可以简单地让 EJB 容器处理实例化,使用如下所示的 @EJB
注释。
@Stateless
public class MyInterfaceImpl {
@EJB
AnotherInterface anotherInterfaceImpl;
public SomeOtherType getMeSomeType() {
//Some implementation details...
return anotherInterfaceImpl.someMethod();
}
}
我希望能够为我正在使用的外部库做(类似的事情),因为这允许我:
- 更改当前正在使用的底层外部库,对我的代码库进行最小的更改。如果需要的话,可能会换成更好的。
- 当我想对
MyInterfaceImpl
class. 进行单元测试时,轻松注入模拟
到目前为止我看过-
创建一个包装器方法,其参数为
ExternalLibrary
,因此可以执行某种手动方法参数注入。这仍然使我的实现与底层库紧密耦合。 (或者我做的不对)使用
Context & Dependency Injection
容器进行注入(就像EJB 容器那样做。我知道它不一样)。研究了使用Producers
的能力。尽管我了解Producers
对 CDI 的作用,但我无法理解如何利用它?或者即使我走在正确的道路上?
更新: 我找到了几篇帮助我更好地理解 CDI Producers 的文章,我尝试采用这种方法,但遇到了另一个问题。所以现在我有:
ExternalLibraryProducer.java
public class ExternalLibraryProducer {
@Produces
private ExternalLibraryClass1 extrnalLibraryClassProducer() {
return new ExternalLibraryClass1("SomeString", 7);
//The constructor actually takes a string and another commplex type
//as parameters. I am keeping it a little simple here.
//I am trying to set the ExternalLibraryClass1() arguments
//programmatically at runtime.
}
}
现在,我要生成的对象的构造函数接收参数,比方说字符串和整数。我想我可以创建一个 Qualifier
来传递这些参数来生成我想要的对象。
ExternalLibraryClass1Qualifier.java
@Qualifier
@Retention(RUNTIME)
@Target({METHOD})
public @interface ExternalLibraryClass1Qualifier {
String argument1();
Int argyment2(); //This is actually another complex type. Keeping it
//simple here.
}
现在我想做的是,我希望在运行时以编程方式设置参数值(假设来自属性文件)。而且我不知道该怎么做。所以我的最终注射如下所示。
@Stateless
public class MyInterfaceImpl {
@Inject
@ExternalLibraryClass1Qualifier(argument1 = "something", argument2 = 7)
ExternalLibrary externalLib;
public SomeType getMeSomeType() {
//Some implementation details...
return externalLib.externalLibMethod();
}
}
感谢您的指导。
您可以让 ExternalLibrary
的生产者方法接受创建对象所需的参数,并且可以通过 CDI 生产者生成这些参数。
public class ExternalLibraryProducer {
private String name;
private int age;
public ExternalLibraryProducer() {
// set name and age from properties file or elsewhere
// or you can set them individually on their respective producer methods, but might be costly considering you need to read the properties file twice
}
@Produces
public String name() {
return name;
}
@Produces
public int age() {
return age;
}
....
@Produces
private ExternalLibraryClass1 extrnalLibraryClassProducer(String name, int age) {
// Or you can use them directly here, if you opt to not separate this config from the dependencies
return new ExternalLibraryClass1(argument, age);
}
}
CDI 生产者是一种方法,唯一的问题是,您究竟想如何构建它们。
既然你说参数来自 属性 文件,我建议你反转方法并让生产者方法检查 属性 文件并提取值(或询问任何 "reader" 之前这样做并缓存它):
@Produces
private ExternalLibraryClass1 produceExternalLibraryInstance() {
// read the properties from the file or from any cache you use
String arg1 = PropertyReader.getarg1();
Integer arg2 = PropertyReader.getArg2();
// create object with those args
return new ExternalLibraryClass1(arg1, arg2);
}
有了这个你显然不需要限定符然后可以简单地做 @Inject ExternalLibraryClass1
.
请注意,当您创建注入 ExternalLibraryClass1
的对象时,将调用生产者 - 确保您可以尽快从 属性 文件中获取参数。 (当 produces 读取时应该不会有问题,如果你有一些缓存可能会更棘手)