我也谈谈guice, 简单就是美

Guice轻量级IOC容器
本文探讨了Google Guice作为轻量级IOC容器的优势,包括其小巧的体积、高性能及简单易用等特点。文章还介绍了Guice的核心架构设计与使用建议。

一直以来, 我都是spring的忠实fans, 使用它也有好几年了.
看着它从1.0发展到现在的2.5, 给我感觉就是, 长大了, 而且逐渐成为一个成熟的一站式解决方案.

但有的时候, 我只想要一个ioc容器, 它还合适吗?
于是焦点定位在了google的guice. 当然轻量级容器有很多, hivemind, picoContainer, plexus 等都不错的, 但是他们生不逢时, guice是在java最重要的几个特性发布后, 才诞生的, 本身设计理念上要好一些.

选择有以下几点理由:

1, 它的身材很小, jar包只有500多k.功能上, 是一个纯净的ioc容器, 不会有过多依赖.
2, 08年获得了jolt award.(不是主要理由)
3, 性能大幅超越spring.(不过号称spring2.5也提性能了)
3, 开发调试比较简单, 直接new一个容器, 不需要载入配置文件就可以用了.
4, 官方文档内容比较精简, 看完应该不需要1个小时, 那么, 学习成本又降低了.
5, 开发者是google的工程师, 并且google内部大量使用该框架, 维护不成问题.
6, 基于annotation, 不需要引入配置文件的复杂性, 离代码更近. 当然, annotation存在低侵入性, 这可能是它唯一的缺点.(适用于移植性要求不高或只需对外暴露服务的项目.)
7, 支持静态注入.

如果还没看过guice的朋友, 只需要耽误你半个小时, 看看这位网友写得一篇总结, 短小精悍, 总结

架构设计

guice injector结构

从图中可以看到, Injector包含N个binding(类跟实例的绑定关系)组成, binding是在创建Injector时, 由指定的Module或guice提供的一些辅助annotation(比如implementBy)生成的.
每个binding由 key , scope, provider组成, 其中scope可以不需要, 默认是原型, 也可以自己指定singleton等.
key是binding的唯一描述, 一般包含类和annotation, 其中annotation不是必须的, 但有annotation可以使同一个类对应不同子类或接口实现.
每一个binding都对应一个provider, 用于生成实例, 维护实例的生命周期. 类似Factory.

业务代码主要是通过injector来获取依赖注入后的实例.

注入流程:
注入流程序列图

使用建议

1, guice有3种注入方式, constructor, setter, field.
其中field注入是最简单的, 它支持直接向private field进行注入, 实现上, 是通过反射改变accessible, 避免了jvm的安全检查.

如果项目不需要考虑以后移植到spring或其他ioc容器的话, 用成员变量注入会方便很多.

2, Injector里有个叫 injectMember 的方法, 用于针对指定对象触发注入.
这个, 感觉适用于在基类里操作.可以减少guice跟业务代码的耦合.

比如单元测试的容器初始化基类, web应用的controller里注入model等.

3, guice里有个设计是, 通过自定义的annotation来为同一个接口注入不同的实例.(类似spring里的bean id)
这里, 在binding的时候, annotationWith 可以使用 Names.named() 这个静态方法避免新写annotation, 来生成一个指定名字的 NamedImpl 对象, 它是 @Named 这个annotation接口的实现.

guice注入的时候, 就是通过判定你写的 @Named(“xx”) 跟你注册的 NamedImpl 对象是否equals.

4, 通常不建议使用guice里提供的额外annotation, 比如 在接口上指明ImplementedBy(xx.class),说明该接口的默认实现是xx.class, 这种方式使接口依赖于实现, 当你的xx.class实现改名后, 连编译都通不过.
还有一个在实现类上, 注释 singleton 表示单例scope的, 也跟 implementedBy 类似, 有侵入性.

还是推荐在 Module 里设置 binding, 相当于配置的作用.

5, 建议将常量配置在外部 properties 里, 然后在Mdoule里配置binding时, 通过Names.bindProperties 工具方法将properties里定义的key-value字符串注册到guice容器里.代码里只要使用 @Named(“key name”) 就可以注入了.

6, 不要忽视Stage, 即 PRODUCTION(生产环境) 和 DEVELOPMENT(开发环境)对bean的实例化规则.前者会在容器初始化时, 实例化所有的bean. 后者会在使用到该bean时, 才实例化.
所以, 生产环境没必要用lazy init, 大胆选用 PRODUCTION.

7, 如何控制类似spring的InitializingBean和init-method这种生命周期动作?
guice里可以通过编写 Provider 实现init动作, 这里推荐自己搞个annotation,比如@init-method, 然后在provider里反射判定, 调一把.

另外, 还有一种更原始的方式 就是在构造函数调init.

8, 单元测试的时候, 针对一些需要初始化很久的bean, 用bind(StartupTask.class).asEagerSingleton()先初始化.

9, 编写 Module 时, 继承 AbstractModule, 可以简化binding配置代码.

03-18
<think>好的,我现在需要帮助用户了解Google Guice框架的使用教程和示例。首先,我应该先回顾用户提供的引用内容,看看里面有哪些关键点可以利用。用户给出的四个引用主要提到了Guice的基本使用、依赖注入、模块配置、作用域(Scopes)、与其他框架的集成(如Play框架)、Maven依赖以及一些扩展工具比如Dagger。 首先,用户的问题是关于Guice的使用教程和示例,所以需要从基础开始,逐步引导用户。可能需要先介绍什么是依赖注入(DI),然后说明Guice作为轻量级DI框架的特点。接着,按照引用中的信息,分步骤讲解如何设置Guice,比如添加Maven依赖(引用4中的内容),创建模块类继承AbstractModule,配置绑定(引用1中的典型使用),以及作用域的应用(引用3中的Scopes)。 然后,结合示例代码会更直观。引用4提到了简单的示例代码,需要展示一个基本的Guice注入例子,包括定义接口、实现类、模块配置和主类中使用Injector获取实例。此外,用户可能对作用域比较感兴趣,比如单例作用域,这在引用3中提到过,应该用示例说明如何使用@Singleton注解。 另外,用户可能想知道Guice的生态系统和扩展,比如与Dagger的比较(引用2),可以简要提及。同时,结合引用1提到的实际应用案例,比如Elasticsearch和Netty内部使用Guice,可以强调Guice的实际应用价值,增加可信度。 需要确保回答结构清晰,分步骤讲解,每个步骤都有对应的示例代码或配置说明。同时,检查是否符合系统级指令,比如数学公式的格式、LaTeX正确性、中文回答,并在最后生成相关问题。引用标识要自然添加在引用的内容末尾,例如关于Scopes的部分引用[^3],Maven依赖引用[^4]等。 可能还需要注意术语的准确性,比如正确使用“绑定”、“注入”、“作用域”等术语,避免错误。另外,用户可能对Guice与其他框架(如Spring)的区别感兴趣,但引用中没有提到,所以可能暂时不涉及,专注于教程和示例。 最后,生成的相关问题需要围绕Guice的进阶使用、最佳实践、与其他工具集成等方面,比如如何管理依赖配置、与Play框架的集成、性能优化等,参考用户提供的引用内容中的相关点。</think>### Google Guice 框架使用教程与示例 Google Guice 是一个轻量级依赖注入(DI)框架,通过模块化配置管理对象实例及其依赖关系,广泛应用于中间件和工具组件(如 Elasticsearch、Netty)[^1]。以下是基础使用步骤和示例: --- #### 1. **添加 Maven 依赖** 在项目的 `pom.xml` 中添加依赖(版本可更新): ```xml <dependency> <groupId>com.google.inject</groupId> <artifactId>guice</artifactId> <version>5.1.0</version> </dependency> ``` --- #### 2. **定义接口与实现类** 假设需要注入一个服务类: ```java // 接口 public interface MessageService { void sendMessage(String msg); } // 实现类 public class EmailService implements MessageService { @Override public void sendMessage(String msg) { System.out.println("Email sent: " + msg); } } ``` --- #### 3. **配置绑定关系** 创建模块类继承 `AbstractModule`,定义接口与实现的绑定: ```java public class AppModule extends AbstractModule { @Override protected void configure() { bind(MessageService.class).to(EmailService.class); } } ``` --- #### 4. **使用注入器获取实例** 通过 `Injector` 获取对象实例: ```java public class Main { public static void main(String[] args) { Injector injector = Guice.createInjector(new AppModule()); MessageService service = injector.getInstance(MessageService.class); service.sendMessage("Hello Guice!"); } } ``` 输出结果:`Email sent: Hello Guice!` --- #### 5. **作用域(Scopes)** Guice 支持通过作用域控制实例生命周期。例如,单例模式: ```java public class AppModule extends AbstractModule { @Override protected void configure() { bind(MessageService.class).to(EmailService.class).in(Scopes.SINGLETON); } } ``` [^3] --- #### 6. **与 Play 框架集成** 在 Play 框架中,可通过 `Guice.createInjector` 指定开发/生产环境: ```java Stage stage = Play.mode.isDev() ? Stage.DEVELOPMENT : Stage.PRODUCTION; Injector injector = Guice.createInjector(stage, new AppModule()); ``` --- #### 7. **扩展工具** - **Guice Extensions**:提供辅助注入(`assistedinject`)、依赖图生成(`grapher`)等功能。 - **Dagger**:Google 另一款 DI 框架,侧重编译时检查和性能优化[^2]。 --- ### 总结 Guice 的核心价值在于简化对象依赖管理,尤其适用于模块化程度高、需灵活配置的场景。其轻量级特性使其成为中间件和工具库的理想选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值