Google Guice 2:Mental Model

news/2025/2/18 17:59:26/

1. 序言

1.1 Guice中的键值对

  • 上一篇博客,《Google Guice 1:如何实现依赖注入》,讲解了如何利用Guice实现依赖注入

  • 现在,将注意力放回到EmailModule,它继承了AbstractModule,重写了configure()方法

  • 在configure()方法中,通过bind().to()EmailService接口绑定到具体的实现类QQEmailService

    public class EmailModule extends AbstractModule {@Overrideprotected void configure() {bind(EmailService.class).to(QQEmailService.class);}
    }
    
  • 当应用程序需要EmailService类型的实例时,Guice会自动提供一个QQEmailService实例

  • bind().to()这样的语法,就像定义了一个键值对,Key<EmailService> →\rightarrow Provider<EmailService>

  • 接口Provider<T>的定义如下,其中get()方法负责提供一个T的实例

    interface Provider<T> {/** Provides an instance of T.**/T get();
    }
    
  • Provider<EmailService>的伪代码如下,提供一个单例的EmailService实例

    class EmailServiceProvider implements Provider<EmailService> {private static final EmailService instance = new QQEmailService();@Overridepublic EmailService get() {return instance; }
    }
    

1.2 键值对 →\rightarrow Guice map

  • 这些键值对,形成了Guice map,其Key可以使用Key.get()去构建

    Key<EmailService> emailService = Key.get(EmailService.class);
    
  • 通过Guice显示或隐式获取实例时,将从Guice map中获取绑定好的对象

    • 显式获取实例:injector.getInstance(EmailService.class),显式获取EmailService实例
    • 隐式获取实例:通过injector.getInstance(EmailClient.class)显式获取EmailClient实例时,Guice会自动注入EmailService实例。EmailService实例,是Guice从Guice map中隐式获取的
  • 从Guice map获取EmailService的核心伪代码如下:

    Provider<EmailService> provider = guiceMap.get(Key.get(EmailService.class)); // key为Key<EmailService>
    return provider.get();
    

2. Guice is a map

  • 通过前面的学习,不难发现:Guice通过map实现对象的管理,可以说,Guice is a map是Guice的Mental Model
  • Mental Model:心智模型?心理模型?总之,就是Guice的建模思路
  • 使用Guice的两个重要环节,也是围绕map展开的
    • Configuration:在Guice module中配置Guice map,或者使用Just-In-Time bindings,自动创建对象的键值映射
    • Injection:当应用程序需要时,Guice可以从map中创建并检索对象,从而实现依赖注入
  • Just-In-Time bindings,简称JIT bindings,又叫implicit bindings,隐式绑定

2.1 Configuration

  • Guice module的官方解释:

    A Guice module is a unit of configuration logic that adds things into the Guice map。
    Guice module是一个配置逻辑单元,可以将事物(键值对,又叫binding)添加到Guice map中

  • 在Guice module中,可以使用Guice DSL(Domain Specific Language ),配置Guice map

  • 主要有以下几种DSL(其中,value部分使用了lambda表达式):

    Guice DSL syntaxMental model描述
    bind(key).toInstance(value)map.put(key, () -> value)instance binding,实例对象与key的绑定
    bind(key).to(anotherKey)map.put(key, map.get(anotherKey))linked binding, 绑定关系就像链条,环环相扣
    @Provides Foo provideFoo() {...}map.put(Key.get(Foo.class), module::provideFoo)provider method binding,使用@Provides标识一个方法,并在方法中定义对象的创建逻辑
    bind(key).toProvider(provider)map.put(key, provider)provider binding,当provider method binding变得越来越复杂时,可以考虑创建一个独立的Provider类去定义对象的创建逻辑
  • 《Google Guice 1:如何实现依赖注入》中,使用的是instance binding,EmailService --> () -> qqEmailService

    bind(EmailService.class).to(QQEmailService.class);
    

2.2 Injection

  • 对象的创建依赖其他对象,你无需主动从Guice map中获取这些对象(dependency),而是直接声明you need something,Guice则会自动注入这些对象
  • Guice中,声明当前类或方法依赖其他对象的方式如下:
    • 使用@Inject注解标识构造函数、字段、setter方法
      class Foo {private Database database;@InjectFoo(Database database) {  // We need a database, from somewherethis.database = database;}
      }
      
    • @Provides标识的方法,为其传入参数
      @Provides
      Database provideDatabase(@DatabasePath String databasePath) { // 在创建Databas前,需要注入 @DatabasePath 标识的Stringreturn new Database(databasePath);
      }
      
  • PS:依赖的注入不止发生在dependent class中,在Guice module中,也存在依赖注入

3. 总结

  • Guice实现依赖注入的几个关键点:
    • 首先,以键值对的形式定义对象的创建逻辑,放入到Guice map中
    • 其次,通过@Inject@Provides标识的方法的入参,来声明此处需要依赖注入
    • 最后,获取某个需要依赖注入的实例对象(dependent obeject)时,Guice Injector根据依赖关系,从Guice map中获取对象(dependency)并注入,从而完成dependent obeject的创建与初始化
  • 整个过程中,Guice is a map,存储了对象的创建逻辑,是整个Guice的Mental Model

http://www.ppmy.cn/news/10636.html

相关文章

分布式事务方案分析:两阶段和TCC方案(图+文)

1 缘起 补充事务相关知识过程中&#xff0c; 发现&#xff0c;默认的知识都是基于单体服务的事务&#xff0c;比如ACID&#xff0c; 然而&#xff0c;在一些复杂的业务系统中&#xff0c;采用微服务架构构建各自的业务&#xff0c; 就有了分布式事务的概念&#xff0c;比如&am…

vue3中的写法以及,一些语法糖

vue3新增setup&#xff0c;属性执行比 created更早,同时setup中this不会指向实例&#xff09;这个方法在onBeforeMounted之前被调用。定义数据需要在数据前面加ref&#xff0c;ref在vue3中是将数据转换成响应式数据结构的一种,因为vue3中没有了data(){ },那么就没办法劫持数据做…

TypeScript学习(四)函数

文章目录1.定义函数2.函数类型3.可选类型和默认参数4.剩余参数5.this1.定义函数 使用function关键字来定一个函数。 function hello() {console.log("hello") }hello(); // hello2.函数类型 和变量一样&#xff0c;在TypeScript中&#xff0c;函数同样可以像变量一样…

宝塔Linux面板安装MySQL数据库,并且开启远程链接

1.宝塔面板【软件商店】->【应用搜索】&#xff0c;搜索MySQL,然后点击安装想要的版本&#xff0c;我这边是安装的5.6版 2. 安装完后重置数据库管理员密码 3.Navicat Premium 15连接数据库 4.外网navicat工具无法连接数据库的处理办法 4.1输入 mysql -u root -p 后回车&a…

我与CSDN2022年的故事

目录 人生之中&#xff0c;初识博客 踏上csdn博客之路 审核成后的10分钟 第一条博客成功发布 得到恩师的鼓励 发布后的二十分钟 星星之火&#xff0c;可以燎原 每时每刻&#xff0c;都在博客 开发热爱&#xff0c;愈发癫狂 传播之路&#xff0c;渐渐开始 泥泞路上&a…

9.Isaac教程-- Laikago 四足机器人的自主导航

Laikago 四足机器人的自主导航 开发智能机器人系统是一项多学科的工作&#xff0c;集成了动力学、控制、计算机视觉、人工智能等。 很难掌握所有这些领域。 即使你掌握了所有这些&#xff0c;也需要花费大量时间才能正确和稳健。 为了帮助机器人专家加速智能机器人的开发&…

架构设计---用户加密处理

前言&#xff1a; 在互联网各种安全问题中&#xff0c;最能引发话题&#xff0c;刺激大众神经的就是用户的泄密问题&#xff0c;数据库被拖库导致所有的数据泄露&#xff0c;这种系统安全问题涉及的因素可能有很多&#xff0c;大部分和开发软件的程序员没有关系&#xff0c;但…

SOA 和微服务有何区别?

玩过 Dubbo 的小伙伴应该都有听说过一个概念叫做 SOA&#xff0c;每当我们说起微服务的时候&#xff0c;很多人就会去纠结这和 SOA 有啥关系呀&#xff1f;感觉换汤不换药呀。 今天松哥来稍微和小伙伴们讨论下这个话题&#xff0c;我们一起来看看 SOA 和微服务到底有何异同。 …