在带有 CDI 的 Java EE 平台中,可以注入(inject) POJO 类的实例。 以非常简单的方式,我们需要使用@Inject 注释来注入(inject)某个接口(interface)的默认实例。我们也可以使用限定符将具体类注入(inject)我们的领域。 但这些解决方案是相当静态的。
我需要一些更动态的注入(inject)东西模型。
介绍一下我的问题: 假设我们有接口(interface) Animal 和实现该接口(interface)的三个类:Ant、Dog、Elephant。 我想动态注入(inject)这三个类之一的实例,它取决于一些变量,如字符串(动物名称)。 在 Java SE 中,我会这样做:
Map<String, Animal> animalMap = new HashMap<>();
animalMap.put("ant", new Ant());
animalMap.put("dog", new Dog());
animalMap.put("elephant", new Elephant());
...
String animalName = ...;
Animal animal = animalMap.get(animalMap);
animal.doSomething();
所以我需要这样的东西:
class AnimalManager {
@Inject // ?
private Animal animal; // ?
public void run(String animalName) {
// based on animalName get new instance of animal and run doSomething()
...
animal.doSomething(); // if animalName is "ant" call the doSomething on Ant class
}
}
在所有实现 Animal 接口(interface)的类中,我需要使用带有@EJB 注释的变量。
在 Java EE 中最好和最合适的方法是什么?
编辑:
好的,基于 Svetlin Zarev 和 hwellmann 的回复(谢谢!)我创建了这个:
一开始我们将创建动物模型:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface AnimalModel {
Type value();
enum Type { ANT, DOG, ELEPHANT }
}
让我们创建动物:
public interface Animal {
public void eat(Object food);
}
接下来,具体类:
@AnimalModel(AnimalModel.Type.ANT)
public class Ant implements Animal {
@Override
public void eat(Object food) {
...
}
}
@AnimalModel(AnimalModel.Type.DOG)
public class Dog implements Animal {
@Override
public void eat(Object food) {
...
}
}
@AnimalModel(AnimalModel.Type.ELEPHANT)
public class Elephant implements Animal {
@Override
public void eat(Object food) {
...
}
}
接下来,AnimalLiteral:
public class AnimalLiteral extends AnnotationLiteral<AnimalModel> implements AnimalModel {
private static final long serialVersionUID = 1L;
private Type type;
public AnimalLiteral(Type type) {
this.type = type;
}
public Type value() {
return type;
}
}
主要组件是动物工厂:
@Dependent
public class AnimalFactory {
@Inject
@Any
private Instance<Animal> animals;
private static Map<String, AnimalModel.Type> animalMap;
public AnimalFactory() {
animalMap = new HashMap<>();
animalMap.put("ant", AnimalModel.Type.ANT);
animalMap.put("dog", AnimalModel.Type.DOG);
animalMap.put("elephant", AnimalModel.Type.ELEPHANT);
}
public Animal getAnimal(String animalName) {
AnimalModel.Type type = animalMap.get(animalName);
AnimalLiteral literal = new AnimalLiteral(type);
Instance<Animal> animalInstance = animals.select(literal);
return animalInstance.get();
}
}
和客户:
public class Client {
@Inject
private AnimalFactory animalFactory;
public void run(String animalName) {
Animal animal = animalFactory.getAnimal(animalName);
animal.eat("some food...");
}
}
我不知道把 map animalMap放在那个地方是对的...?
最佳答案
使用 Instance<T>结合限定符是 CDI 中执行动态注入(inject)的标准方式。
您需要一个带有绑定(bind)参数的限定符,例如@Species("ant")区分您的实现类。
public class AnimalSelector {
@Inject
@Any
private Instance<Animal> animals;
public Animal selectAnimalBySpecies(String speciesName) {
SpeciesLiteral qualifier = new SpeciesLiteral(speciesName);
return animals.select(qualifier).get();
}
}
public class SpeciesLiteral extends AnnotationLiteral<Species> implements Species {
private String name;
public SpeciesLiteral(String name) {
this.name = name;
}
@Override
public String value() {
return name;
}
}
@Qualifier
@Target({ TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
public @interface Species {
String value() default "";
}
关于java - 通过 CDI 动态注入(inject)实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33583032/
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_