带有属性文件的CDI工厂设计模式

问题描述 投票:0回答:2

我有一个这样的界面:

@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 
} 

有人可以帮助我吗?

java jakarta-ee cdi java-ee-8
2个回答
0
投票

惯用的方法是使用限定符,但要在 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;
       }
    } 
}

0
投票

我终于找到了一个好的解决方案。
其实我们还需要

@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();
    }
}

工作了。
谢谢你。

© www.soinside.com 2019 - 2024. All rights reserved.