You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Guice与pac4j时遇play.cache.SyncCacheApi未绑定错误求助

问题解决:Guice注入SyncCacheApi失败

问题原因

你直接用main方法运行Guice注入,但Play的SyncCacheApi是Play框架运行时才会自动绑定的依赖,普通Java SE环境下Guice找不到它的具体实现类,所以报错No implementation for play.cache.SyncCacheApi was bound。而你参考的demo是运行在Play应用内部,Play的Guice模块已经自动处理了Cache相关的绑定。

解决方案

有两种可行的解决方式:

方案1:模拟Cache实现(用于本地测试)

如果只是想验证Guice注入逻辑,可以手动绑定一个SyncCacheApi的测试实现,比如用Guava Cache模拟:

  1. 先添加Guava依赖到build.gradle:
implementation "com.google.guava:guava:32.1.3-jre"
  1. 修改AuthModule,手动绑定测试实现:
package org.example;

import com.google.inject.*;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.play.store.PlayCacheSessionStore;
import org.pac4j.play.store.PlaySessionStore;
import play.cache.SyncCacheApi;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

class AuthModule extends AbstractModule {

    @Override
    protected void configure() {
        // 绑定模拟的SyncCacheApi实现
        bind(SyncCacheApi.class).toInstance(new SyncCacheApi() {
            private final Cache<String, Object> cache = CacheBuilder.newBuilder()
                    .expireAfterWrite(1, TimeUnit.HOURS)
                    .build();

            @Override
            public <T> T get(String key) {
                return (T) cache.getIfPresent(key);
            }

            @Override
            public <T> T getOrElseUpdate(String key, Callable<T> block, int expiration) {
                try {
                    return cache.get(key, block);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public <T> T getOrElseUpdate(String key, Callable<T> block) {
                return getOrElseUpdate(key, block, 0);
            }

            @Override
            public void set(String key, Object value, int expiration) {
                cache.put(key, value);
            }

            @Override
            public void set(String key, Object value) {
                set(key, value, 0);
            }

            @Override
            public void remove(String key) {
                cache.invalidate(key);
            }
        });

        // 现在可以正常获取SyncCacheApi的Provider并创建实例
        final PlayCacheSessionStore playCacheSessionStore = new PlayCacheSessionStore(getProvider(SyncCacheApi.class));
        bind(SessionStore.class).toInstance(playCacheSessionStore);
        bind(PlaySessionStore.class).toInstance(playCacheSessionStore);
    }

}

class AuthenticationController {
    @Inject
    private PlaySessionStore _playSessionStore;

    public void printSomething() {
        System.out.println(_playSessionStore);
    }
}

class GuiceTester {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new AuthModule());
        AuthenticationController authenticationController = injector.getInstance(AuthenticationController.class);
        authenticationController.printSomething();
        System.out.println("hello");
    }
}

方案2:在Play应用环境中运行代码

如果是实际开发场景,应该把代码放到Play应用中运行:

  • 将AuthModule作为Play模块注册到application.conf:play.modules.enabled += "org.example.AuthModule"
  • Play启动时会自动绑定SyncCacheApi的官方实现(基于配置的缓存组件,比如Ehcache),此时你的注入逻辑就能和参考的demo一样正常工作。

额外说明

  • Play的play-cache模块提供的默认SyncCacheApi实现是DefaultSyncCacheApi,但它依赖Play运行时环境,无法在普通Java程序中直接实例化。
  • 测试场景下也可以使用Play官方提供的FakeSyncCacheApi,需要添加testImplementation "com.typesafe.play:play-test_2.12:2.8.18"依赖,然后在测试类中调用使用。

内容的提问来源于stack exchange,提问作者al2co33

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:05:27