notebooks
  • notebooks
  • _planning
    • 2022 OKR
    • basketball
    • swimming
  • communication
    • Dubbo
    • Kafka
    • Messaging
    • RPC
    • Thrift
  • computation
    • map-reduce
  • cs-basic-knowledge
    • computer-architecture
    • data-structure-and-algorithms
    • networks
    • os
  • devops
    • Docker
    • Linux
    • Prometheus
    • operations
    • security
    • trouble-shooting
  • distributed-knowledge
    • Zookeeper_CMD
    • distributed-system
  • game-engine
    • Unity
  • others
    • appium使用
  • protocols
    • http(s)协议
    • 官方链接
    • sip
  • storage
    • Elasticsearch
    • GuavaCache
    • MySQL
    • MySQL_CMD
    • NoSQL
    • Redis
    • Redis_CMD
  • system-design
    • system-design
  • tools
    • Git
    • IDEA
    • Mac
    • VScode
    • Vim
  • _working
    • doc-template
      • backend-design-review
      • correction-of-error
      • service-review
    • process
      • domain-backup
      • oncall
  • blogs
    • history
      • 8088/8086微处理器
      • 8088/8086指令系统
      • CSS-DOM
      • CSS定位
      • CSS工作原理
      • CSS控制背景
      • CSS浮动布局
      • CSS盒模型
      • Chrome开发者工具使用方法
      • DOM
      • Django Model模型层学习
      • Django-REST-framework Serializers学习
      • Django-REST-framework Views和ViewSets学习
      • Django View视图层学习
      • Gvim下Emmet安装及使用教程
      • HTTP协议简介
      • HashMap原理初探
      • JavaScript简史
      • JavaScript语法
      • Java内存模型和GC机制
      • Java基础——Lambda学习
      • Java基础——方法引用
      • Java基础——枚举类型
      • Java类加载机制
      • KMP算法
      • Kafka学习
      • Linux下用命令行编译Java程序
      • MathJax简介和基本用法
      • Python实现常见数据结构
      • Python装饰器总结
      • TCP协议的三次握手和四次挥手
      • Thrift学习
      • asyncio学习
      • markdown的常用语法
      • 修改hosts文件实现翻墙
      • 充实文档的内容
      • 关系数据库
      • 关系数据库标准语言SQL(一)
      • 关系数据库标准语言SQL(二)
      • 关系数据理论
      • 关系查询处理和查询优化
      • 内联元素和块级元素
      • 剑指offer算法题练习
      • 动态创建标记
      • 图形化用户界面
      • 在Eclipse中使用Maven构建Java Web项目
      • 增加微博秀遇到的一些问题
      • 处理机调度
      • 如何用github和hexo搭建个人博客
      • 存储管理
      • 存储系统的层次结构
      • 学习模仿lionhit网站首页的过程总结
      • 实用的GitHub小技巧
      • 并发控制
      • 循环与分支程序设计
      • 指令系统的设计
      • 指令级并行及其开发——硬件方法
      • 搭建自己的VPN服务器
      • 操作系统用户界面
      • 数据库安全性
      • 数据库完整性
      • 数据库恢复技术
      • 数据库绪论
      • 数据库编程
      • 数据库设计
      • 数据抽象
      • 文件系统
      • 文法和语言
      • 最佳实践
      • 案例研究:JavaScript图片库
      • 案例研究:图片库改进版
      • 汇编语言程序格式
      • 汇编语言程序设计基础知识
      • 流水线技术
      • 深度优先搜索和广度优先搜索
      • 牛客网——网易2017秋招编程题集合
      • 用JavaScript实现动画效果
      • 第一篇博客
      • 经典排序算法总结(Java实现)
      • 经典查找算法总结(Java实现)
      • 综合示例
      • 编译原理引论
      • 背包、队列和栈
      • 虚拟机安装Linux系统及常用软件
      • 计算机操作系统绪论
      • 计算机系统结构的基础知识
      • 设备管理
      • 设计模式之代理模式
      • 设计模式之单例模式
      • 设计模式之工厂模式
      • 设计模式之策略模式
      • 设计模式之观察者模式
      • 词法分析
      • 进程管理
      • 闭包
      • 阻止Google自动跳转到香港服务器的方法
      • 项目部署过程
  • programming-language
    • C#
      • C#
    • C&C++
      • C
    • C&C++
      • C++
    • Java
      • GoogleGuice
    • Java
      • JVM
    • Java
      • Java
    • Java
      • Maven
    • Java
      • Mybatis
    • Java
      • Spring知识
    • Java
      • SpringBoot
    • Java
      • Tomcat
    • Python
      • Python
    • Shell
      • Shell
  • wheels
    • dcc
      • 产品调研
      • 方案设计
    • red-envelope
      • 方案设计
    • short-url
      • 短链接服务
    • sso
      • 方案设计
Powered by GitBook
On this page
  • GoogleGuice用法
  • Guice模块
  • Guice 和 Spring 区别
  1. programming-language
  2. Java

GoogleGuice

GoogleGuice用法

1.通过继承AbstractModule,在configure方法里面定义接口和对应的实现,也就是说定义了从interface到implementation的绑定。然后再每个类的构造函数上加Inject注释,这样Guice就可以自动的帮助类去传递constructor的参数,并且知道如何把接口和实现对应起来。

public class BillingModule extends AbstractModule {
  @Override 
  protected void configure() {
    bind(TransactionLog.class).to(DatabaseTransactionLog.class);
    bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
    bind(BillingService.class).to(RealBillingService.class);
  }
}

public class RealBillingService implements BillingService {
  private final CreditCardProcessor processor;
  private final TransactionLog transactionLog;

  @Inject
  public RealBillingService(CreditCardProcessor processor,
      TransactionLog transactionLog) {
    this.processor = processor;
    this.transactionLog = transactionLog;
  }

2.Linked Bindings:类型到实现的绑定(bind a type to its implementation)。 如果一个类型,对应着多个实现,比如说,一个interface,有3个子类的实现,那么就需要一个key来分辨不同的子类实现。这个key就是注释。

// 自定义一个PayPal注释
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME)
public @interface PayPal {}

// 绑定注释对应的实现
bind(CreditCardProcessor.class)
        .annotatedWith(PayPal.class)
        .to(PayPalCreditCardProcessor.class);

// 使用注释
public class RealBillingService implements BillingService {

  @Inject
  public RealBillingService(@PayPal CreditCardProcessor processor,
      TransactionLog transactionLog) {
    ...
  }

然后使用这个注释,告诉Guice,如果你看到这个注释PayPal,就把这个类型CreditCardProcessor替换成指定的实现子类PayPalCreditCardProcessor。

3.Provides 方法绑定:适用于对象的创建需要多行代码,多个步骤,就把这几行代码放入一个单独的方法中,并加上Provides注释

public class BillingModule extends AbstractModule {
  @Override
  protected void configure() {
    ...
  }

  @Provides
  @PayPal
  TransactionLog provideTransactionLog() {
    // 对象的创建需要多步
    DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();
    transactionLog.setJdbcUrl("jdbc:mysql://localhost/pizza");
    transactionLog.setThreadPoolSize(30);
    return transactionLog;
  }
}

4.Provider 类绑定:适用于如果前面的Provides方法还是很复杂,那么可以把它单独做成一个类,用于对象的创建。

public interface Provider<T> {
  T get();
}
// 自定义一个provider来创建TransactionLog
public class DatabaseTransactionLogProvider implements Provider<TransactionLog> {
  private final Connection connection;

  @Inject
  public DatabaseTransactionLogProvider(Connection connection) {
    this.connection = connection;
  }

  public TransactionLog get() {
    DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();
    transactionLog.setConnection(connection);
    return transactionLog;
  }
}
// 绑定TransactionLog到DatabaseTransactionLogProvider,也就是告诉Guice使用
// DatabaseTransactionLogProvider来创建TransactionLog类型对象
public class BillingModule extends AbstractModule {
  @Override
  protected void configure() {
    bind(TransactionLog.class)
        .toProvider(DatabaseTransactionLogProvider.class);
  }

5.Constructor Bindings 构造函数绑定:一个类型的绑定,取决于其构造函数的参数。前面的几个例子,proivder,provides,都需要手动的构造依赖。而Constructor Binding要解决的问题就是:在不需要手动的构造依赖的情况下,自动的根据依赖的构造函数,来完成依赖注入

public class BillingModule extends AbstractModule {
  @Override 
  protected void configure() {
    try {
      // TransactionLog这个接口绑定到 DatabaseTransactionLog这个类
      // 并且选择需要DatabaseConnection作为参数的那个构造函数(也就是第三种),来完成初始DatabaseTransactionLog
      bind(TransactionLog.class).toConstructor(
          DatabaseTransactionLog.class.getConstructor(DatabaseConnection.class));
    } catch (NoSuchMethodException e) {
      addError(e);
    }
  }
}

// DatabaseTransactionLog有多个构造函数,但是只有第三种构造函数会被使用
public class DatabaseTransactionLog implements TransactionLog {
   public DatabaseTransactionLog() {....}
   public DatabaseTransactionLog(String jdbcUrl) {....}
   public DatabaseTransactionLog(DatabaseConnection conn) {....}
   
}

6.JIT bindings:及时类型绑定。

@ImplementedBy(PayPalCreditCardProcessor.class)
public interface CreditCardProcessor {
  ChargeResult charge(String amount, CreditCard creditCard)
      throws UnreachableException;
}
//等价于
bind(CreditCardProcessor.class).to(PayPalCreditCardProcessor.class);

@ProvidedBy(DatabaseTransactionLogProvider.class)
public interface TransactionLog {
  void logConnectException(UnreachableException e);
  void logChargeResult(ChargeResult result);
}
//等价于
bind(TransactionLog.class).toProvider(DatabaseTransactionLogProvider.class)

Guice模块

在一个项目中,你可以创建任意多个Guice的Module(继承AbstractModule),当项目不断地增大,越来越多的Module会遍布于各处,如果一个Module依赖于另一个Module,那就很麻烦了。会带来两个问题:

  • 如何管理Guice Module间的依赖?一个解决方法是创建一个top level的ApplicationModule,然后把所有的Module在其中加载。

  • 如何更好的划分Guice Module?最常见的是根据package边界来划分和创建Module,一个package一个Module:module-per-package。此方法最大的好处就是所有的implementation都只是package private的,这就强制了使用你的api的用户,针对接口编程,而不是依赖于具体的实现。

Guice 和 Spring 区别

  1. Guice更偏向于以注释的方式来解决依赖注入的逻辑,这种方式能在简洁性和可维护性之间取得最好的平衡。Spring要么是XML注释,要么是auto wiring,在Guice看来,前者太琐碎,后者太隐式。

PreviousJavaNextJava

Last updated 3 years ago