我有一个这样的界面:
@Singleton
public interface StorageEngine {
String upload(InputStream inputStream);
InputStream download(String fileName);
int size(String fileName);
boolean delete(String fileName);
}
以及多重实施:
public class LocalFileSystemEngine implements StorageEngine {
// Implement methods ...
}
public class DropboxEngine implements StorageEngine {
// Implement methods ...
}
public class GoogleDriveEngine implements StorageEngine {
// Implement methods ...
}
还有这个 Producer 类:
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Any;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.Produces;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ApplicationScoped
public class StorageProducer {
private static final Logger logger = LoggerFactory.getLogger(StorageProducer.class);
@Inject
@ConfigProperty(name = "storage.engine-type",defaultValue = "local-filesystem")
private String engineType;
@Inject
@Any
private Instance<StorageEngine> storageEngineInstance;
@Produces
public StorageEngine getStorageEngine() {
// How to implement ???
}
}
我的目标是:
从 microprofile 属性文件中读取引擎类型并生成存储引擎。
有没有办法在没有限定符注释的情况下注入
StorageEngine
?
我只需要在注入点类上有这个:
@MultipartConfig
@WebServlet(urlPatterns = "/file")
public class FileServlet extends HttpServlet {
@Inject
private StorageEngine storageEngine;
// Implement service method
}
有人可以帮助我吗?
惯用的方法是使用限定符,但要在 getStorageEngine() 中使用它们。
@Produces
public StorageEngine getStorageEngine() {
if (engineType.equals("type one")) {
//TypeOne.class is a qualifier
storageEngineInstance.select(TypeOne.class);
} else if //repeat for all engine types
}
如果你真的不想使用限定符,Instance也是可迭代的
@Produces
public StorageEngine getStorageEngine() {
if (StorageEngine storageEngine : storageEngineInstance) {
if (storageEngine.someValue().equals(engineType.someValue())) {
return storageEngine;
}
}
}
我终于找到了一个好的解决方案。
其实我们还需要
@Qualifier
注释.
首先创建一个这样的注释:
@Qualifier
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StorageType {
String value();
}
现在为此创建注释文字:
public class StorageTypeLiteral extends AnnotationLiteral<StorageType> implements StorageType {
private final String value;
public StorageTypeLiteral(String value) {
this.value = value;
}
@Override
public String value() {
return value;
}
}
更改实施:
@StorageType("local-filesystem")
public class LocalFileSystemEngine implements StorageEngine {
// Implement methods ...
}
@StorageType("Dropbox")
public class DropboxEngine implements StorageEngine {
// Implement methods ...
}
@StorageType("GoogleDrive")
public class GoogleDriveEngine implements StorageEngine {
// Implement methods ...
}
现在像这样更新生产者类:
@ApplicationScoped
public class StorageProducer {
private static final Logger logger = LoggerFactory.getLogger(StorageProducer.class);
@Inject
@ConfigProperty(name = "storage.engine-type",defaultValue = "local-filesystem")
private String engineType;
@Inject
@Any
private Instance<StorageEngine> storageEngineInstance;
@Produces
public StorageEngine getStorageEngine() {
Instance<StorageEngine> instance = storageEngineInstance.select(new StorageTypeLiteral(engineType));
if (!instance.isResolvable())
throw new IllegalArgumentException("Storage %s not implemented yet".formatted(engineType));
return instance.get();
}
}
工作了。
谢谢你。