【问题标题】:Accessing injected properties results in NullPointerException访问注入的属性会导致 NullPointerException
【发布时间】:2021-07-30 09:46:50
【问题描述】:

这是我第一次使用 Quarkus 和 CDI,我想我弄错了。

在我的应用程序中,用户可以下载一些文件。我想控制同时下载多少个文件。我想我可以通过创建一个带有@ApplicationScoped 注释的bean,在启动时强制实例化,然后在我需要知道当前正在下载多少文件的地方注入它。

这是我设法做到的:

@ApplicationScoped
public class DownloadState {
    private int downloadingFiles;

    void startup(@Observes StartupEvent event) {
        setDownloadingFiles(0);
        System.out.println("downloading files: " + downloadingFiles);
    }

    public int getDownloadingFiles() {
        return downloadingFiles;
    }

    public void setDownloadingFiles(int downloadingFiles) {
        this.downloadingFiles = downloadingFiles;
    }

    public void incrementDownloadingFiles() {
        downloadingFiles++;
    }

    public void decrementDownloadingFiles() {
        downloadingFiles--;
    }
}

这样做我可以在启动时看到日志显示“正在下载文件:0”,所以我知道该类已被实例化。

我在这里尝试访问下载文件的数量:

public class Downloader {
    private static final Logger LOG = Logger.getLogger(Downloader.class);

    @Inject
    DownloadState downloadState;

    private Dotenv dotenv = Dotenv.configure()
        .directory("../")
        .filename(".env.local")
        .load();

    private String fileName = dotenv.get("DOWNLOAD_PATH");
    private String url;

    public Downloader(String url, String fileName) {
        this.url = url;
        this.fileName += fileName;
    }

    public void downloadProduct() {

        LOG.info("Downloading Files: " + downloadState.getDownloadingFiles());
        //...
    }
}

每当调用 downloadProduct 时,都会在 LOG.info("Downloading Files: " + downloadState.getDownloadingFiles()); 行上抛出 NullPointerException

我的 CDI 完全错了吗?任何帮助都非常感谢,提前谢谢你。

【问题讨论】:

    标签: java cdi quarkus


    【解决方案1】:

    我假设您直接调用Downloader 构造函数——在这种情况下,确实不会发生注入,您的downloadState 将是null。依赖注入具有“传染性”——你必须在任何地方使用它。

    在你的情况下,我可能只创建Downloader@ApplicationScoped,在你使用它的任何地方注入它,并且可能将urlfileName 参数从构造函数移动到downloadProduct。实际上,此时downloadingFiles 的数量也可能在Downloader 中。 (还要注意它可以从多个线程访问——所以我可能会使用AtomicInteger 来代替downloadingFiles。)

    总而言之,是这样的:

    @ApplicationScoped
    public class Downloader {
        private static final Logger LOG = Logger.getLogger(Downloader.class);
    
        private final AtomicInteger downloadingFiles = new AtomicInteger(0);
    
        private final String downloadPath = Dotenv.configure()
            .directory("../")
            .filename(".env.local")
            .load()
            .get("DOWNLOAD_PATH");
    
        public void downloadProduct(String url, String fileName) {
            String path = downloadPath + fileName;
    
            int current = downloadingFiles.incrementAndGet();
            LOG.info("Downloading Files: " + current);
            //...
        }
    }
    

    【讨论】:

    • 非常感谢!我以前通过一个热切的单身人士“解决”了我的问题,但我更喜欢这种方法!顺便说一句,我不确定 CDI 是否更好以及为什么更好,我会进一步调查。再次感谢:)
    猜你喜欢
    • 1970-01-01
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多