2

我在我的 spigot 插件中使用 Guice 的辅助注入时遇到问题,并且似乎无法缩小问题范围。这是我得到的错误:

> [12:00:38 INFO]: [DestinyMC] Enabling DestinyMC v1.0
> 2019-01-14 12:00:41,492 Log4j2-TF-1-AsyncLogger[AsyncContext@5c647e05]-1 ERROR An exception occurred processing Appender File com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalStateException: zip file closed
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2217)
    at com.google.common.cache.LocalCache.get(LocalCache.java:4154)
    at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4158)
    at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5147)
    at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:5153)
    at com.google.inject.internal.util.StackTraceElements.forMember(StackTraceElements.java:71)
    at com.google.inject.internal.Messages.formatSource(Messages.java:241)
    at com.google.inject.internal.Messages.formatSource(Messages.java:220)
    at com.google.inject.internal.Messages.formatMessages(Messages.java:90)
    at com.google.inject.CreationException.getMessage(CreationException.java:50)
    at org.apache.logging.log4j.core.impl.ThrowableProxy.<init>(ThrowableProxy.java:134)
    at org.apache.logging.log4j.core.impl.ThrowableProxy.<init>(ThrowableProxy.java:122)
    at org.apache.logging.log4j.core.async.RingBufferLogEvent.getThrownProxy(RingBufferLogEvent.java:330)
    at org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter.format(ExtendedThrowablePatternConverter.java:61)
    at org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:38)
    at org.apache.logging.log4j.core.layout.PatternLayout$PatternSelectorSerializer.toSerializable(PatternLayout.java:455)
    at org.apache.logging.log4j.core.layout.PatternLayout.toText(PatternLayout.java:232)
    at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:217)
    at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:57)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:177)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:170)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:161)
    at org.apache.logging.log4j.core.appender.RollingRandomAccessFileAppender.append(RollingRandomAccessFileAppender.java:218)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
    at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:448)
    at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:433)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
    at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:79)
    at org.apache.logging.log4j.core.async.AsyncLogger.actualAsyncLog(AsyncLogger.java:337)
    at org.apache.logging.log4j.core.async.RingBufferLogEvent.execute(RingBufferLogEvent.java:161)
    at org.apache.logging.log4j.core.async.RingBufferLogEventHandler.onEvent(RingBufferLogEventHandler.java:45)
    at org.apache.logging.log4j.core.async.RingBufferLogEventHandler.onEvent(RingBufferLogEventHandler.java:29)
    at com.lmax.disruptor.BatchEventProcessor.processEvents(BatchEventProcessor.java:168)
    at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:125)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalStateException: zip file closed
    at java.util.zip.ZipFile.ensureOpen(Unknown Source)
    at java.util.zip.ZipFile.getEntry(Unknown Source)
    at java.util.jar.JarFile.getEntry(Unknown Source)
    at java.util.jar.JarFile.getJarEntry(Unknown Source)
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:120)
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:104)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at com.google.inject.internal.util.StackTraceElements$1.load(StackTraceElements.java:49)
    at com.google.inject.internal.util.StackTraceElements$1.load(StackTraceElements.java:45)
    at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3716)
    at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2424)
    at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2298)
    at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2211)
    ... 39 more

这是我的活页夹类:

public class MainBinder extends AbstractModule {

@Override
protected void configure() {
    bind(DestinyMC.class).toInstance(this.plugin);

    install(new FactoryModuleBuilder().build(InventoryFromFileFactory.class));
}

当我注释掉安装行时,错误消失了。那条线使用这个工厂类

public interface InventoryFromFileFactory {
    InventoryFromFile create(String targetRootKey, String targetFile);
}

其中声明了在创建此类对象时需要手动提供的参数:

public class InventoryFromFile {
    @Inject
    public InventoryFromFile
    (
        @Assisted String targetRootKey,
        @Assisted String targetFile,
        ConfigAccessorFactory configAccessorFactory
    )
    {
        ConfigurationSection targetCS = configAccessorFactory.create(targetFile).getCustomConfig().getConfigurationSection(targetRootKey);
    ...
    }
}

ConfigAccessFactory是另一个辅助注入的工厂类

public interface ConfigAccessorFactory {
    ConfigAccessor create(String filename);
}

在这里使用:

public class ConfigAccessor {
    private Plugin plugin;
    private final String customFileName;

    @Inject
    public ConfigAccessor
    (
        @Assisted String fileName,
        DestinyMC plugin
    )
    {
        this.customFileName = fileName;
        this.plugin = plugin;
    }
    ...
}

最后,DestinyMC依赖是 spigot 插件的主类:

public class DestinyMC extends JavaPlugin {
//Inject dependencies
@Inject private ConfigAccessorFactory configAccessorFactory;

//Code only run once when the plugin is enabled
public void onEnable() {
    MainBinder mainBinder = new MainBinder(this);
    Injector injector = Guice.createInjector(mainBinder);
    injector.injectMembers(this);

    //Saves config files to disk if they don't exist
    saveDefaultConfig();
    Arrays.asList(
        "inventory-gui.yml",
        "player-tree-template.yml",
        "player-tree-data.yml"
    ).forEach((file) -> {
        configAccessorFactory.create(file).saveDefaultConfig();
    });
    ...
}

我不太确定我做错了什么,但我对 Guice 还很陌生,所以我很可能误解了一些东西。另外,如果有更好的方法可以做到这一点,请告诉我。谢谢您的帮助。

4

0 回答 0