当前位置: 首页 > news >正文

一文彻底理解 Google 依赖注入(DI) 框架 Guice

文章目录

    • 什么是Guice
    • 什么是DI(依赖注入)
    • 为什么需要依赖注入?
    • 如何进行依赖注入 ?
    • 依赖注入的方式
    • @Provides 与 @Inject 的区别
    • Guice和Spring的对比

什么是Guice

Guice(发音同"juice")是Google于2007年开源的一款轻量级依赖注入(Dependency Injection,DI)框架。作为Java平台上的IoC容器实现,它通过注解驱动的方式简化了依赖管理,是Spring框架之外的重要选择。通常用在非Spring的项目中,实现依赖注入的功能。

核心特性包括:

  1. 基于JSR-330标准实现,使用@Inject等标准注解
  2. 采用编译时验证机制,能在启动阶段发现大部分配置错误
  3. 相比Spring更轻量,启动速度更快(基准测试显示启动时间可缩短50%以上)

典型应用场景:

  • 需要精细控制对象生命周期的应用(如服务器中间件)
  • 对启动性能敏感的服务(如命令行工具)

什么是DI(依赖注入)

依赖注入就是:

把一个对象需要的依赖(即它所依赖的其他对象),从外部“注入”进去,而不是自己在内部创建。通俗一点讲:
• 不再由类自己去 new 出它需要的对象;
• 而是由一个“容器”(比如 Spring 或 Guice)帮你创建这些对象,并自动传给需要它们的类。

举个例子
✅ 没有依赖注入的写法

public class UserService {private final UserRepository repo;public UserService() {this.repo = new UserRepository(); // ❌ 直接在这里 new}public void createUser(String name) {repo.save(name);}
}

👉 这样写的问题:
1. UserService 强依赖具体实现 UserRepository;
2. 你无法轻易换成别的实现,比如 MockUserRepository;
3. 测试时不方便(没法注入 mock 对象);
4. 对象的生命周期(什么时候创建、销毁)不好统一管理。

那使用依赖注入的写法:

public class UserService {private final UserRepository repo;// 依赖通过构造函数注入@Injectpublic UserService(UserRepository repo) {this.repo = repo;}
}

然后在 Guice 或 Spring 里配置:

Guice:

public class MyModule extends AbstractModule {@Overrideprotected void configure() {bind(UserRepository.class).to(PostgresUserRepository.class);}
}

Spring:

@Service
public class UserService {private final UserRepository repo;@Autowiredpublic UserService(UserRepository repo) {this.repo = repo;}
}

👉 这样容器会自动:
• 创建 PostgresUserRepository;
• 创建 UserService;
• 并把前者注入给后者。

为什么需要依赖注入?

  • 解耦 类不再依赖于具体实现,只依赖接口。
  • 可替换性 可以在不同环境(dev/test/prod)注入不同实现。
  • 易测试 单元测试中可注入 mock 对象。
  • 生命周期管理 容器统一管理对象的创建、销毁、单例/多例。

如何进行依赖注入 ?

举个例子

  1. 定义一个服务类
public interface AddressService {String queryCity();
}@Singleton
public class BaiduAddressService implements AddressService {@Overridepublic String queryCity() {return "百度地图";}
}@Singleton
public class GaodeAddressService implements AddressService {@Overridepublic String queryCity() {return "高德地图";}
}
  1. 创建依赖使用者(Consumer)
@Singleton
public class UserService {private final AddressService addressService;@Injectpublic UserService(@Named("gaodeAddressService") AddressService addressService) {this.addressService = addressService;}public void queryUser() {System.out.println(addressService.queryCity());}
}

💬 解释:

  • @Inject 表示构造函数由 Guice 自动注入
  • @Named(“gaodeAddressService”),用于区分不同实现;
  • 依赖关系通过构造函数明确表达。
  1. 配置 Guice 模块(Module)
public class ServiceModule extends AbstractModule {@Overrideprotected void configure() {// 绑定接口到实现bind(AddressService.class).annotatedWith(Names.named("gaodeAddressService")).to(GaodeAddressService.class);bind(AddressService.class).annotatedWith(Names.named("baiduAddressService")).to(BaiduAddressService.class);}// 使用 @Provides 提供复杂对象@Provides@Singletonpublic DataSource provideDataSource() {HikariConfig config = new HikariConfig();config.setJdbcUrl("jdbc:postgresql://localhost:5432/testdb");config.setUsername("test");config.setPassword("test");return new HikariDataSource(config);}
}

💬 解释:
• bind(…).to(…):声明接口与实现的映射;
• @Provides:当类无法直接用 @Inject 创建时,手动提供一个“工厂方法”;就是不能通过构造函数这种方式创建对象时。
• @Singleton:让对象全局只创建一次。

  1. 启动并获取对象
public class Client {public static void main(String[] args) {Injector injector = Guice.createInjector(new ServiceModule());UserService userService = injector.getInstance(UserService.class);userService.queryUser(); // 输出: 高德地图}
}
  • Guice.createInjector(…) 创建依赖注入容器;
  • injector.getInstance(…)
  • 从容器中获取实例;
  • 所有依赖(UserService → AddressService)自动注入完成

依赖注入的方式

注入方式代码示例优点缺点
✅ 构造函数注入@Inject public UserService(AddressService a)依赖明确,不可变依赖较多时构造函数冗长
⚙️ 字段注入@Inject private AddressService a;代码简洁隐藏依赖关系,难以测试
🧩 方法注入@Inject void setAddressService(AddressService a)适合可选依赖或循环依赖不够直观,延迟初始化时使用

@Provides 与 @Inject 的区别

特性@Inject@Provides
用法在构造函数或字段上标注在 Module 中定义方法
目的让 Guice 自动构造对象手动定义复杂对象的创建逻辑
适用场景类能被直接构造类构造逻辑复杂、或需外部依赖

Guice和Spring的对比

Overall:

特性GuiceSpring
注解@Inject, @Provides, @Singleton@Autowired, @Service, @Component
配置方式手动声明 Module自动扫描 classpath
优点轻量、启动快、显式依赖自动化、生态完善
典型场景微服务、工具、内部服务企业应用、大型项目

注解比较:

功能Spring Boot 注解Guice 注解说明
声明依赖注入点@Autowired@InjectGuice 遵循 JSR-330 标准,与 Spring 的 @Autowired 类似。
声明组件/服务@Component, @Service, @Repository, @Controller无对应注解(需在 Module 中绑定)Spring 自动扫描这些 Bean;Guice 需要显式在 Module 里 bind()
构造函数注入@Autowired 放在构造函数上@Inject 放在构造函数上两者都支持构造函数注入。
提供自定义实例@Bean(在 @Configuration 类中)@Provides(在 AbstractModule 中)两者都用于手动创建并返回依赖对象。
限定注入(多实现选择)@Qualifier("beanName")@Named("name") 或自定义 @BindingAnnotation都可用于在多个实现中指定要注入哪一个。
生命周期管理@PostConstruct, @PreDestroy无内置支持(需手动管理)Spring 自动管理 Bean 生命周期;Guice 更加简单直接。
配置类声明@Configurationextends AbstractModuleSpring 用配置类声明 Bean;Guice 用模块绑定依赖。

希望看完本文后,你对Guice有一个彻底的理解,并且能够顺利应用到项目中。

http://www.dtcms.com/a/530092.html

相关文章:

  • 天龙八部TLBB系列 - OgreSE工具详细介绍
  • 大连做网站公司阿里云网站备案要多久
  • 怎么建立公司的网站吗重庆巨能建设集团网站
  • 北京市建设网莱芜网站建设优化
  • 未来5-10年,HDD仍然不可替代!
  • 【Linux进程间通信二】System V 共享内存和消息队列
  • 公司网站的维护汕头网站制作网页
  • 图书馆网站建设方案设计论文湖南网站建设推荐
  • 柳州做网站的企业外包做网站需要多少钱
  • 做淘宝货源网站网站主页设计模板
  • 做网站的公司怎样收费12380网站建设情况
  • 减少网站跳出率目前好的推销网站
  • 苏州网站建设运营推广咸鱼网站交易付款怎么做
  • 做网站开发前景如何谈一谈对网站开发的理解
  • 南乐网站建设电话wordpress 5发布
  • 平顶山营销型网站建设清远最新通知
  • 江苏网站推广商标设计网站推荐
  • 建设企业网站需注意什么中国建设劳动学会网站
  • 服务器网站打开慢建设银行人才招聘官方网站
  • 网页设计制作网站html代码杭州网络科技公司排名
  • 上传到网站的根目录中四川成都旅游必去十大景点推荐
  • 宝塔建设网站上海的网站开发公司电话
  • 怎么看网站是否织梦门户网站建设滞后
  • 深喉咙企业网站官方网站建设需求规格说明书
  • 做相亲网站犯法吗vs2015做网站的后端
  • 新源网站建设手机网站模板源码
  • Linux中文件路径解析函数path_walk的实现
  • 群辉wordpress东莞市网络优化推广服务机构
  • 网站建设的安全威胁wordpress customize.php
  • 学做快餐的视频网站传奇网页版游戏开服表