CDI:注入单个实例有效,但注入 Instance<> 无效。为什么?
CDI: Injecting single instance works, but injecting Instance<> does not. Why?
我试图在 CDI 注入的帮助下实现某种 "plugin feature"。但我遇到了一些麻烦,我想我可能会从我的同伴那里得到一些外部观点 "Stackers" :-)
到目前为止,我已经知道这样的东西是有效的:
@Inject
@ScoringModule("AGE")
private AgeModule ageModule;
@Inject
@ScoringModule("CUSTOMER_TYPE")
private CustomerTypeModule customerTypeModule;
当我 "run" 这两个字段都注入了适当的实例。但是当我尝试像这样向它们注入更多 "dynamically" 时:
@Inject @Any
private Instance<CustomerScoringModule> scoringModuleInstance;
CustomerScoringModule module = scoringModuleInstance.select(new ScoringModuleLiteral("AGE")).get();
然后我会得到这样的异常:
org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type CustomerScoringModule with qualifiers @Any @ScoringModule
这对我来说似乎很奇怪,因为 CDI 清楚地 "knows" 关于我感兴趣的实例,因为直接注入到类型字段中是有效的。所以我假设它一定与预选赛有关?不知何故 CDI "sees" 这两个实例,但决定其中 none 适合我的注入请求?会是这样吗?
有没有什么 "obvious" 想到我可能做错了?我是第一次尝试使用 CDI,我有可能(甚至很可能)在某个地方做了一些愚蠢的事情:-)
感谢任何帮助或提示,并提前致谢!
下面附上"surrounding" 类限定词和注解文字等供参考
两个模块实现的CustomerScoringInterface:
package de.otto.cccs.customerscoring.modules;
import de.otto.cccs.customerscoring.modules.vo.ScoringModuleResponseVO;
import de.otto.cccs.customerscoring.valueobjects.webservice.ScoringRequestVO;
public interface CustomerScoringModule {
public ScoringModuleResponseVO process(ScoringRequestVO inputVO);
}
两个模块实现之一(它们现在只是虚拟实现,唯一的区别是 process() 方法中的 log.info() 输出,这就是为什么我在这里只包括其中一个) :
package de.otto.cccs.customerscoring.modules;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import de.otto.cccs.customerscoring.modules.qualifiers.ScoringModule;
import de.otto.cccs.customerscoring.modules.vo.ScoringModuleResponseVO;
import de.otto.cccs.customerscoring.valueobjects.webservice.ScoringRequestVO;
import lombok.extern.log4j.Log4j2;
@Log4j2
@Stateless
@LocalBean
@ScoringModule("AGE")
public class AgeModule implements CustomerScoringModule {
public AgeModule() {
super();
}
@Override
public ScoringModuleResponseVO process(ScoringRequestVO inputVO) {
log.info("processed AGE_MODULE");
return new ScoringModuleResponseVO();
}
}
@ScoringModule 限定符:
package de.otto.cccs.customerscoring.modules.qualifiers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Qualifier
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ScoringModule {
String value();
}
以及注释文字:
package de.otto.cccs.customerscoring.modules.qualifiers;
import javax.enterprise.util.AnnotationLiteral;
public class ScoringModuleLiteral extends AnnotationLiteral<ScoringModule> implements ScoringModule {
private static final long serialVersionUID = 1L;
private String value;
public ScoringModuleLiteral(String value) {
this.value = value;
}
@Override
public String value() {
return this.value;
}
}
最后我空了beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
我最终将模块从 EJB 更改为普通 Java 类,我所有的麻烦都消失了。
我并不真的需要这些模块是 EJB,我只是在开始时错误地假设它们必须通过 CDI 注入,现在不再是这种情况了(旧的 J2EE 版本确实如此)
感谢反馈!
我试图在 CDI 注入的帮助下实现某种 "plugin feature"。但我遇到了一些麻烦,我想我可能会从我的同伴那里得到一些外部观点 "Stackers" :-)
到目前为止,我已经知道这样的东西是有效的:
@Inject
@ScoringModule("AGE")
private AgeModule ageModule;
@Inject
@ScoringModule("CUSTOMER_TYPE")
private CustomerTypeModule customerTypeModule;
当我 "run" 这两个字段都注入了适当的实例。但是当我尝试像这样向它们注入更多 "dynamically" 时:
@Inject @Any
private Instance<CustomerScoringModule> scoringModuleInstance;
CustomerScoringModule module = scoringModuleInstance.select(new ScoringModuleLiteral("AGE")).get();
然后我会得到这样的异常:
org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type CustomerScoringModule with qualifiers @Any @ScoringModule
这对我来说似乎很奇怪,因为 CDI 清楚地 "knows" 关于我感兴趣的实例,因为直接注入到类型字段中是有效的。所以我假设它一定与预选赛有关?不知何故 CDI "sees" 这两个实例,但决定其中 none 适合我的注入请求?会是这样吗?
有没有什么 "obvious" 想到我可能做错了?我是第一次尝试使用 CDI,我有可能(甚至很可能)在某个地方做了一些愚蠢的事情:-)
感谢任何帮助或提示,并提前致谢!
下面附上"surrounding" 类限定词和注解文字等供参考
两个模块实现的CustomerScoringInterface:
package de.otto.cccs.customerscoring.modules;
import de.otto.cccs.customerscoring.modules.vo.ScoringModuleResponseVO;
import de.otto.cccs.customerscoring.valueobjects.webservice.ScoringRequestVO;
public interface CustomerScoringModule {
public ScoringModuleResponseVO process(ScoringRequestVO inputVO);
}
两个模块实现之一(它们现在只是虚拟实现,唯一的区别是 process() 方法中的 log.info() 输出,这就是为什么我在这里只包括其中一个) :
package de.otto.cccs.customerscoring.modules;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import de.otto.cccs.customerscoring.modules.qualifiers.ScoringModule;
import de.otto.cccs.customerscoring.modules.vo.ScoringModuleResponseVO;
import de.otto.cccs.customerscoring.valueobjects.webservice.ScoringRequestVO;
import lombok.extern.log4j.Log4j2;
@Log4j2
@Stateless
@LocalBean
@ScoringModule("AGE")
public class AgeModule implements CustomerScoringModule {
public AgeModule() {
super();
}
@Override
public ScoringModuleResponseVO process(ScoringRequestVO inputVO) {
log.info("processed AGE_MODULE");
return new ScoringModuleResponseVO();
}
}
@ScoringModule 限定符:
package de.otto.cccs.customerscoring.modules.qualifiers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Qualifier
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ScoringModule {
String value();
}
以及注释文字:
package de.otto.cccs.customerscoring.modules.qualifiers;
import javax.enterprise.util.AnnotationLiteral;
public class ScoringModuleLiteral extends AnnotationLiteral<ScoringModule> implements ScoringModule {
private static final long serialVersionUID = 1L;
private String value;
public ScoringModuleLiteral(String value) {
this.value = value;
}
@Override
public String value() {
return this.value;
}
}
最后我空了beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
我最终将模块从 EJB 更改为普通 Java 类,我所有的麻烦都消失了。
我并不真的需要这些模块是 EJB,我只是在开始时错误地假设它们必须通过 CDI 注入,现在不再是这种情况了(旧的 J2EE 版本确实如此)
感谢反馈!