Google Guice介绍

发布于:2025-09-09 ⋅ 阅读:(22) ⋅ 点赞:(0)

一、Guice 的基本原理

Guice 通过 Java 注解(如 @Inject)和模块(Module)来描述对象的依赖关系。它在应用启动时,自动分析依赖,并为你创建和注入所需的对象实例。

  • 依赖注入(DI):将对象的创建和依赖转交给框架管理,降低耦合。
  • 控制反转(IoC):对象不再主动获取依赖,而是由容器(Guice)主动提供。

二、核心概念与结构

  1. @Inject 注解

    • 标记需要注入的构造器、字段或方法。
    • 例如:
      class Service {
          @Inject
          public Service(Repository repo) { ... }
      }
      
  2. Module(模块)

    • 通过继承 AbstractModule,在 configure() 方法中绑定接口与实现。
    • 例如:
      public class AppModule extends AbstractModule {
          @Override
          protected void configure() {
              bind(Repository.class).to(RepositoryImpl.class);
          }
      }
      
  3. Injector(注入器)

    • Guice 的容器,用于创建和管理对象实例。
    • 例如:
      Injector injector = Guice.createInjector(new AppModule());
      Service service = injector.getInstance(Service.class);
      
  4. Provider(提供者)

    • 用于复杂或需要动态创建的依赖。
    • 例如:
      public class MyProvider implements Provider<Repository> {
          public Repository get() { ... }
      }
      
  5. @Singleton(单例)

    • 标记该类只创建一个实例。
    • 例如:
      @Singleton
      class Service { ... }
      

三、常用用法详解

1. 构造器注入

class UserService {
    private final UserRepository userRepository;

    @Inject
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

2. 字段注入

class UserService {
    @Inject
    UserRepository userRepository;
}

3. 方法注入

class UserService {
    private UserRepository userRepository;

    @Inject
    public void setUserRepository(UserRepository repo) {
        this.userRepository = repo;
    }
}

4. 绑定接口到实现

在模块中配置:

public class AppModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(UserRepository.class).to(UserRepositoryImpl.class);
    }
}

5. 绑定到特定实例

bind(String.class).toInstance("Hello Guice!");

6. 使用 Provider

bind(UserRepository.class).toProvider(UserRepositoryProvider.class);

7. 作用域管理

单例:

bind(UserService.class).in(Singleton.class);

或者直接在类上加 @Singleton 注解。


四、进阶用法

1. 命名绑定(@Named)

当有多个实现时,可以用 @Named 区分:

bind(PaymentService.class).annotatedWith(Names.named("PayPal")).to(PayPalPaymentService.class);

class OrderService {
    @Inject
    @Named("PayPal")
    PaymentService paymentService;
}

2. 自定义注解绑定

@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface PayPal {}

bind(PaymentService.class).annotatedWith(PayPal.class).to(PayPalPaymentService.class);

class OrderService {
    @Inject
    @PayPal
    PaymentService paymentService;
}

3. 多重绑定(Multibinder)

用于集合注入:

Multibinder<PaymentService> multibinder = Multibinder.newSetBinder(binder(), PaymentService.class);
multibinder.addBinding().to(PayPalPaymentService.class);
multibinder.addBinding().to(AlipayPaymentService.class);

@Inject
Set<PaymentService> paymentServices;

4. 生命周期管理

Guice 本身不直接管理对象销毁,但支持 JSR-250(如 @PreDestroy)。


五、Guice 与 Spring 比较

  • Guice 更轻量,专注于依赖注入,配置简单。
  • Spring 功能更全,支持 AOP、事务等,适合大型企业应用。
  • Guice 适合微服务、轻量级项目或对性能敏感的场景。

六、完整示例

// 接口
public interface UserRepository {
    void save(User user);
}

// 实现
public class UserRepositoryImpl implements UserRepository {
    public void save(User user) { System.out.println("User saved!"); }
}

// 服务
public class UserService {
    private final UserRepository userRepository;
    @Inject
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    public void register(User user) {
        userRepository.save(user);
    }
}

// 模块
public class AppModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(UserRepository.class).to(UserRepositoryImpl.class);
    }
}

// 启动
public class Main {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new AppModule());
        UserService service = injector.getInstance(UserService.class);
        service.register(new User());
    }
}

七、常见问题

  • 循环依赖:Guice 不直接支持构造器循环依赖,但可以用 Provider 或字段注入解决。
  • 配置热更新:Guice 本身不支持,需要自定义实现。
  • AOP:Guice 支持方法拦截(见 MethodInterceptor),但功能不如 Spring 全面。

八、更多资源


如需针对某一功能或场景深入讲解,欢迎进一步提问!


网站公告

今日签到

点亮在社区的每一天
去签到