Jakarta ee 如何将没有接口的外部库类注入JavaEE应用程序?
我对JavaEE和依赖注入的概念相当陌生。然而,我对它有一个公平的理解,即使我不知道它可以被使用的所有方式 我有一个本地接口,如下所示:Jakarta ee 如何将没有接口的外部库类注入JavaEE应用程序?,jakarta-ee,dependency-injection,mocking,cdi,Jakarta Ee,Dependency Injection,Mocking,Cdi,我对JavaEE和依赖注入的概念相当陌生。然而,我对它有一个公平的理解,即使我不知道它可以被使用的所有方式 我有一个本地接口,如下所示: @Local public interface MyInterfaceLocal { SomeType getMeSometype(); } 实现此接口的类是无状态EJB @Stateless public class MyInterfaceImpl { public SomeType getMeSomeType() { //
@Local
public interface MyInterfaceLocal {
SomeType getMeSometype();
}
实现此接口的类是无状态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();
}
}
@Stateless
public class MyInterfaceImpl {
@Inject
@ExternalLibraryClass1Qualifier(argument1 = "something", argument2 = 7)
ExternalLibrary externalLib;
public SomeType getMeSomeType() {
//Some implementation details...
return externalLib.externalLibMethod();
}
}
我希望能够对我正在使用的外部库执行(类似的操作),因为这允许我:
MyInterfaceImpl
类进行单元测试时,可以轻松地插入一个mock外部库
,因此可以执行某种手动方法参数注入。这仍然使我的实现与底层库紧密耦合。(或者我做得不对)Context&Dependency Injection
container来进行注入(就像EJB容器那样。我知道这不一样)。研究了使用生产者的能力。虽然我了解制作人
在CDI方面做了什么,但我不知道如何利用这一点?或者即使我走对了路
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
@Retention(RUNTIME)
@Target({METHOD})
public @interface ExternalLibraryClass1Qualifier {
String argument1();
Int argyment2(); //This is actually another complex type. Keeping it
//simple here.
}
现在,我要生成的对象的构造函数接受参数,比如字符串和整数。我想我可以创建一个限定符
来传入这些参数以生成我想要的对象
externallibraryClassQualifier.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
@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 {
@EJB
AnotherInterface anotherInterfaceImpl;
public SomeOtherType getMeSomeType() {
//Some implementation details...
return anotherInterfaceImpl.someMethod();
}
}
@Stateless
public class MyInterfaceImpl {
@Inject
@ExternalLibraryClass1Qualifier(argument1 = "something", argument2 = 7)
ExternalLibrary externalLib;
public SomeType getMeSomeType() {
//Some implementation details...
return externalLib.externalLibMethod();
}
}
感谢您的指导。您可以让
外部库的producer方法接受创建对象所需的参数,并且可以通过CDI producerr生成这些参数
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);
}
}
您可以让ExternalLibrary
的producer方法接受创建对象所需的参数,并且可以通过CDI producerr生成这些参数
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制作人是一种方式,唯一的问题是,你到底想如何构建他们
既然您说参数来自属性文件,我建议您反转方法,让producer方法检查该属性文件并提取值(或者询问之前执行此操作并缓存它的任何“阅读器”):
有了它,您显然不需要限定符,只需执行@injectexternallibraryclass1
只需注意,当您创建一个注入外部libraryClass1
的对象时,将根据调用producer-请确保您很快就能从属性文件中获取args。(当products进行读取时应该不会有问题,如果您有一些缓存,可能会更棘手)CDI products是一种方法,唯一的问题是,您希望如何准确地构建它们
既然您说参数来自属性文件,我建议您反转方法,让producer方法检查该属性文件并提取值(或者询问之前执行此操作并缓存它的任何“阅读器”):
有了它,您显然不需要限定符,只需执行@injectexternallibraryclass1
只需注意,当您创建一个注入外部libraryClass1
的对象时,将根据调用producer-请确保您很快就能从属性文件中获取args。(当PRODUCTS进行读取时应该不会有问题,如果您有一些缓存,可能会更棘手)CDI PRODUCTOR看起来是个不错的方法,尽管这里的限定符参数不起作用-我认为注入点与PRODUCTOR方法不匹配。也许可以反转方法,将argument1
和argument2
存储在制作者在创建对象时可以查看的地方?CDI制作者看起来是个不错的方法,尽管限定符参数在这里不起作用-注入点与我认为的制作者方法不匹配。也许可以颠倒方法,将argument1
和argument2
存储在制作人创建对象时可以查看的地方?