我有一个接口和它的实现,就像这样;
interface MyInterface {
public void doSomething();
}
@Alternative
class MyImpl implements MyInterface {
@Inject DB db;
public void doSomething() {
// db.select ....
}
}
因为我希望能够通过配置文件更改我的数据库,所以使用provider方法生成实现
@Singleton
public class MyApiProvider {
@Produces
public MyInterface getMyApi() {
return new MyImpl();
}
}
当MyImpl类通过getMyApi方法生成时,“@Inject DB db;”在MyImpl类中为null。
所以我想做的就是能够配置在运行时使用的实现。
编辑: 当我删除@Alternative并删除提供程序类/方法时,一切都按预期工作..
编辑2: 我想从配置文件告诉我的webapp我今天要使用哪个MyInterface实现类。明天也许我想要另一个实现,我不想重新编译整个项目。
答案 0 :(得分:1)
这种情况正在发生,因为你正在创建MyImpl
类,而不是让CDI实现它。
当CDI控制对象生命周期时,您只能进行注入(和其他注释处理)。
您正在寻找的是@Qualifier。
可以在beans.xml文件中指定特定的@Alternative
。
或者,您可以尝试以下方式:
@ApplicationScoped
public class Configuration {
public String getMyInterfaceImpl() {
// property file loading logic
}
}
public class SomeClient {
@Inject @Named("#{configuration.myInterfaceImpl}")
private MyInterface myInterface;
...
}
答案 1 :(得分:0)
您可以使用生产者方法,根据属性/参数选择具体实现:
@Produces
public MyInterface myInterface(MyImplA a, MyImplB b) {
return (propertyValueA) ? a : b;
}
因为生产者方法需要实例a和b,所以它们将由容器创建,因此使用注入。
这是一种快速简化的方法,如果您需要更多变体或实例创建费用昂贵,您应该使用CDI BeanManager来获取并选择要返回的bean。