3分钟带你了解:轻量级依赖注入框架Google Guice【享学Java】(下)

简介: 3分钟带你了解:轻量级依赖注入框架Google Guice【享学Java】(下)

注入


常用的注入方式有多种。


  • 简单的单一注入(接口的实现仅有一个类型)
如示例代码


  • Provider注入(具有延迟效果)
@Inject
private Provider<Animal> animal;


对于Provider方式,配置的方式也可这样来提供(类似于@Bean):


/

// 方法上是可以有入参的。但入参请确保已经是容器内的对象
@Provides // 作用类似于@Bean
@Singleton // 若这里不使用该注解,那就是多例,每次都会执行此方法
private Animal getAnimal(){
    return new Dog();
}


需要注意的是,若使用了@Provides方式配置了实例,那么向bind(Animal.class).toInstance(new Dog())这句话就不能再要了,否则就是重复绑定,启动时会抛错:



A binding to com.yourbatman.eurekaclient.guice.Animal was already configured at com.yourbatman.eurekaclient.guice.MainModule.configure(MainModule.java:11).
  at com.yourbatman.eurekaclient.guice.MainModule.getAnimal(MainModule.java:7)
  ...


  • 命名注入:用于对同一接口多个实现类做区分注入


bind(Animal.class).annotatedWith(DogAnno.class).to(Dog.class);
bind(Animal.class).annotatedWith(CatAnno.class).to(Cat.class);
@Inject
@DogAnno
private Animal animal;


除了自定义注解,你还可以使用Guice自带的命令类:Names.named("dog")(它返丝线了注解接口,所以返回值是个注解类型)。


Module之间的关系

创建一个Injector可以使用多个任意多个Module,因此需要明确它们的关系。


  • 并列:默认顺序传递就是此关系


Guice.createInjector(new MainModule(), .......);
  • 嵌套:大的Module可以嵌套任意多个子Module
public class ServerModule extends AbstractModule {
    @Override
    protected void configure() {
        install(new MainModule());
    }
}


  • 覆盖:如果有冲突的话后者覆盖前者,没有的话就都生效


// 用后者覆盖前者
Module finalModule = Modules.override(new MainModule()).with(new ServerModule());


@ImplementedBy 与 @ProvidedBy


单独介绍这两个注解,它是Guice提供的标注在类上的注解,用于简化绑定,他俩可以标注在接口上。


  • @ImplementedB:注解用于简化绑定配置,通常用于指定默认的实现类型。最常用的场景在于编写 Dao 或者 Service 时,指定 Interface 的实现类。
  • @ProvidedBy:作用同上,只不过是通过Provider方式来提供


@ImplementedBy(Dog.class)
// @Singleton // 不能标记在接口上,只能标记在Dog实现类上
public interface Animal {
    void run();
}
@Test
public void fun1() {
  // 注意:并不需要使用使用模块,注解就行哦~~
    Injector injector = Guice.createInjector();
    injector.injectMembers(this);
    System.out.println(animal);
    System.out.println(injector.getInstance(Animal.class));
    System.out.println(injector.getInstance(Animal.class));
    animal.run();
}


这样标注后效果完全同:

bind(Animal.class).to(Dog.class)


@ProvidedBy就不用演示了,它的效果同:

bind(Animal.class).toProvider(DogProvider.class)



Guice和Spring Boot整合


作为主流的微服务开发框架Spring Boot,可以说Guice不可能撼动Spring的江湖地位,其实它也无意去撼动它,乖乖的专心做自己的DI就好。


那么如果一个开源的库是用Guice构建的,而你想在Spring Boot环境下使用肿么办呢???那就是整合。他俩并发冲突,反而也可以一起协作,总的思想有点类似于Spring MVC和Spring的协作:MVC负责请求控制,而Spring负载从当IoC容器,负责DI依赖注入。


当然喽,他俩的集成做不到那么的浑然天成, 思考的思路是:向Spring Boot容器内注入的业务Bean请不要new,请不要new,请不要new,而是通过injector.getInstance(xxx)从Guice里拿,这样便完成了整合。总之就是各自做各自的事,然后通过某个“接口”来完成融合即可,比如这里用Spring Boot总控(其实就是MVC),然后Guice负责管理业务对象之间的依赖关系(如Service、Dao等)。


另外,在web下使用/整合Guice,一般需要导入下面Jar包给与支持:


<dependency>
    <groupId>com.google.inject.extensions</groupId>
    <artifactId>guice-servlet</artifactId>
    <version>4.1.0</version>
</dependency>


Tips:整合过程中,请一定一定一定要注意对象的生命周期以及Scope(Spring Boot一般要单例,而Guice需要做特殊的满足哦~~~)


Guice vs Spring


虽然这两者没有太大的可比性,但由于都是DI框架,所以做一个简单的比较吧。


  • Spring不仅仅是DI,它是一个全家桶技术总和;Guice是个轻量级的DI框架,只聚焦于依赖的管理、注入
  • Spring的配置文件(xml or Confiuration以及扫描的)体现了完整的装配结构;Guice使用Java代码来描述绑定关系
  • Spring使用字符串来表示Bean的key;Guice一般使用类型绑定关系来描述一个实例,且是分模块的、局部的
  • Spring在容器初始化时候完成所有关系的绑定;Guice只记录绑定关系,然后在运行时有需要的时候帮你完成注入
  • 优缺点
  • Spring 的优缺点此处不做说明,主要描述Guice它的DI领域的优缺点。


  • 优点
  • 轻量级(代码量少)
  • 性能优异
  • 良好的泛型支持
  • 因为都用Java语言绑定,所以是强类型的,不容易出错
  • 易于重构Refactor(也得益于是Java代码的强类型)
  • 缺点
  • 学习成本颇高,学习曲线相对陡峭
  • Module的众多绑定规则不太容易理解,导致出错了不易排查
  • 教程少,文档少,中文文档、案例就更少了
  • 社区活跃度无法同Spring相提并论
  • 无法解决循环依赖注入的问题
  • 此问题官方认为不是问题,因为官方建议你通过别的方式避免循环依赖(说明:Spring是解决了循环依赖注入问题的)
  • 编译器支持相对差些(比如它的Guice的AOP不能方便的跳转)


总之,Spring大而全,Guice小而美。企业级应用当然还是推荐使用Spring,而如果你是自己写写组件,不妨用Guice去管理的依赖吧,它能让你的代码结构更加优美且显得不那么臃肿。


当然,理想归理想,说去真心话国内的Java技术毕竟还是阿里这种大厂主导,而非Google系,因此实际生产中若你要使用请三思而后行,毕竟你还有同伴~


总结


关于轻量级依赖注入框架Google Guice就先介绍到这了,相信通过本文的学习,你只需要花几分钟的时间就能了解到Guice的几乎全貌了。


我个人意见,此门DI技术不用深究,但却有必要了解,因为文首说了有些流行的开源框架是基于它构建的,所以了解Guice才能更好的阅读学习其源码。

相关文章
|
19天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
33 3
|
19天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
30 2
|
8天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
8天前
|
消息中间件 Java 数据库连接
Java 反射最全详解 ,框架设计必掌握!
本文详细解析Java反射机制,包括反射的概念、用途、实现原理及应用场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 反射最全详解 ,框架设计必掌握!
|
16天前
|
前端开发 Java 数据库连接
Spring 框架:Java 开发者的春天
Spring 框架是一个功能强大的开源框架,主要用于简化 Java 企业级应用的开发,由被称为“Spring 之父”的 Rod Johnson 于 2002 年提出并创立,并由Pivotal团队维护。
37 1
Spring 框架:Java 开发者的春天
|
14天前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
10天前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
9 1
|
15天前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
15天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
44 5
|
15天前
|
JSON Java 开发工具
Java服务端集成Google FCM推送的注意事项和实际经验
本文分享了作者在公司APP海外发布过程中,选择Google FCM进行消息推送的集成经验。文章详细解析了Java集成FCM推送的多种实现方式,包括HTTP请求和SDK集成,并指出了通知栏消息和透传消息的区别与应用场景。同时,作者还探讨了Firebase项目的创建、配置和服务端集成的注意事项,帮助读者解决文档混乱和选择困难的问题。
23 1