Dagger2公共Module引入已公开Module仍报非公开错误如何解决?
问题排查与解决方案
该报错本质是Dagger的可见性检测逻辑判定被引入的ModuleA对ModuleB无效,即使你声明了public修饰符,可优先排查以下容易忽略的场景:
- 确认
ModuleA是顶级public类,不是嵌套在其他类中的非public内部类,如果是嵌套类需要额外添加static+public修饰,否则默认是包私有可见。 - 若项目使用了Java 9+的JPMS模块化系统,需要在
ModuleA所在JPMS模块的module-info.java中,将ModuleA所在的包export给Dagger注解处理器和ModuleB所在的模块,否则即使类加了public,JPMS也会限制跨模块访问。 - 若是多Gradle模块项目,确认
ModuleB的build.gradle中正确依赖了ModuleA所在的Gradle模块,不要使用runtimeOnly这类仅运行时生效的依赖声明。
如果以上排查均无问题,可以直接添加注解属性绕过Dagger的可见性校验:给ModuleA的@Module注解添加visible = true属性,明确告知Dagger该模块对外可见,修改后代码如下:
@Module(visible = true) public class ModuleA { @Provides @Singleton @Named("classA") public ClassA classA() { return new ClassA(); } }
修改后重新编译即可消除报错。
最佳实践优化建议
你当前的基础写法符合Dagger的使用规范,针对你的场景(ModuleA仅被ModuleB内部引用,不对外暴露)可以做以下优化:
- 既然
ModuleA不需要对外公开,可以直接去掉public修饰符改为包私有,仅保留@Module(visible = true)即可,避免对外暴露不必要的内部实现。 - 建议将
@Named("classA")替换为自定义@Qualifier注解,比字符串形式的Named更安全,编译阶段即可检测出拼写错误,示例如下:
@Qualifier @Retention(RetentionPolicy.RUNTIME) public @interface InternalClassA {}
替换后ModuleA的@Provides方法和ModuleB的注入点都改用@InternalClassA修饰即可。
- 两个
Module都使用了@Singleton作用域,需要确保引用ModuleB的Component也标注了@Singleton,否则会出现作用域不匹配的错误。 - 如果后续没有其他模块需要复用
ModuleA的提供逻辑,可以直接把ClassA的提供方法合并到ModuleB中,减少不必要的Module拆分,降低维护成本。
内容的提问来源于stack exchange,提问作者aagrawal207
相关产品推荐
相关产品推荐

