使用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模拟:
- 先添加Guava依赖到
build.gradle:
implementation "com.google.guava:guava:32.1.3-jre"
- 修改
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
相关产品推荐
相关产品推荐

