`
lv12312
  • 浏览: 10769 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Guice进阶

 
阅读更多
    能跑HelloWorld程序之后,就要开始一点点深入去探寻Guice的奥秘了,未知的领域总是充满了诱惑力,新的东西总是能给人带来无限的激情,这就是为什么人们都喜欢去旅游,去探险的原因之一吧;既然开启了Guice的瓶盖,就好好去尝尝Guice的味道。
 
1、隐式绑定
    之前的Helloworld程序是显式的绑定接口的实现,类似这样的形式: bind(TestService.class).to(TestServiceAnotherImpl.class);Guice提供了一种隐式绑定的方式,给接口默认的实现。如:
TestServiceImpl.java
public class TestServiceImpl implements TestService {
    @Override
    public void info() {
        System.out.println("Say,info");
    }
}
TestService.java
@ImplementedBy(TestServiceImpl.class)
public interface TestService {
    void info();
}
TestServiceModule.java
public class TestServiceModule extends AbstractModule{
    @Override
    protected void configure() {
        bind(TestService.class);
    }
}
TestServiceMain.java
public class TestServiceMain {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new TestServiceModule());
        TestService testService = injector.getInstance(TestService.class);
        testService.info();
    }
}
输出:Say,info
这个时候Module里面就无需显式的绑定实现类 ,自动的绑定默认实现。
但是如果接口又显式定义了另外一个实现呢,那么哪个优先级高一点?
TestServiceAnotherImpl.java
public class TestServiceAnotherImpl implements TestService {
    @Override
    public void info() {
        System.out.println("Say: another!");
    }
}
TestServiceAnotherModule.java
public class TestServiceAnotherModule extends AbstractModule{
    @Override
    protected void configure() {
        bind(TestService.class).to(TestServiceAnotherImpl.class);
    }
}
将这个Module载入Injector,跑起来之后,输出结果:Say:another! 说明Module配置总是高于注解配置。
 
2、对象作用域(Scope)
Guice的默认行为是每次请求对象或者注入的时候都会创建一个新的实例对象。作用域(Scope)能让你自定义对象的生命周期。代码说明一切:
TestSingletonModule.java
public class TestSingletonModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(TestSingleton.class).to(TestSingletonImpl.class);
    }
}
TestSingletonMain.java
public class TestSingletonMain {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new TestSingletonModule());
        TestSingleton testSingleton = injector.getInstance(TestSingleton.class);
        System.out.println(testSingleton);
        TestSingleton testSingleton2 = injector.getInstance(TestSingleton.class);
        System.out.println(testSingleton2);
    }
}
输出:
com.lemon.guice.example2.TestSingletonImpl@535b58
com.lemon.guice.example2.TestSingletonImpl@922804
说明是两个不同的对象
 
当修改一下上述代码,设置成为单例的:
TestSingletonModule.java
public class TestSingletonModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(TestSingleton.class).to(TestSingletonImpl.class).in(Scopes.SINGLETON);
    }
}
上述的TestSingletonMain输出为:
com.lemon.guice.example2.TestSingletonImpl@535b58
com.lemon.guice.example2.TestSingletonImpl@535b58
确实是单例的。
 
说到单例的,大家肯定会想到懒汉式的和恶汉式的单例实现,这个取决于之前所说的Stage的设置。
默认的Stage.DEVELOPMENT是 懒汉式的,Stage.PRODUCTION是饿汉式的,但是在DEVELOPMENT可以使用asEagerSingleton()方法:
bind(TestSingleton.class).to(TestSingletonImpl.class).asEagerSingleton();
显式的使用饿汉式加载方式的。
 
对于Servlet,作用域还有request和session的区别,这个之后再讲。
 
3、对象生产者(Provider)
    在向Guice申请对象的时候,仅仅是找到构造器然后执行它。但是有些时候你并不想这样:
  • 延迟加载
  • 需要类的多个对象
  • 想提供实例生成的自定义实现。
  • 在创建对象的时候需要做其他的一些方式的校验, 在某些情况下需要抛出异常。
  • 想使用第三方包,但是不能直接添加@Inject注解。
  • 需要复用代码的时候。
    首先看看生产者接口:位于Guice jar包内部,继承的是JSR-330 的规范接口
 
public interface Provider<T> extends javax.inject.Provider<T> {
 
  /**
   * Provides an instance of {@code T}. Must never return {@code null}.
   *
   * @throws OutOfScopeException when an attempt is made to access a scoped object while the scope
   *     in question is not currently active
   * @throws ProvisionException if an instance cannot be provided. Such exceptions include messages
   *     and throwables to describe why provision failed.
   */
  T get();
}    
 
    要想使用Provider,首先是实现其接口:
这里沿用 Google Guice这本书的例子:
Gum.java
public class Gum { }
 
GumProvider.java
public class GumProvider implements Provider<Gum> {
    @Override
    public Gum get() {
        return new Gum();
    }
}
GumballMachine.java(对象生产工具,类似工厂)
public class GumballMachine {
    @Inject
    private Provider<Gum> gumProvider;
 
    public Gum dispense(){
        return gumProvider.get();
    }
}
配置的Module
GumModule.java
public class GumModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Gum.class).toProvider(GumProvider.class);
    }
}
然后测试:
GumballExample.java
public class GumballExample {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new GumModule());
        GumballMachine m = injector.getInstance(GumballMachine.class);
        System.out.println(m.dispense());
        System.out.println(m.dispense());
    }
}
 
输出:
com.lemon.guice.example3.Gum@5e3974
com.lemon.guice.example3.Gum@df503
 
这样的话在GumProviderGumballMachine里面就能玩各种花样,在多线程环境下,这样可能存在线程安全问题,这点要注意。
像ImplementedBy注解一样,可以提供@ProvidedBy注解来省去Module的toProvider的配置
@ProvidedBy(GumProvider.class)
public class Gum {
}
 
4、@Named注解
 
这里先抛出一个问题,如果一个接口有多个实现,在不同的条件下使用不同的实现,
如果在Spring中,配置会比较简单,直接在配置文件里面指定实现就Ok,在Guice该肿么解决?
有了@Named注解,就会变得比较方便了。
例子:
Actor.java
public interface Actor {
    void iCanDo();
}
LiXiaolong.java
public class LiXiaolong implements Actor {
 
    @Override
    public void iCanDo() {
        System.out.println("I can do everything!");
    }
}
ZhouXingXing.java
public class ZhouXingXing implements Actor {
    @Override
    public void iCanDo() {
        System.out.println("I'm just an actor!");
    }
}
ActionMovie.java
public class ActionMovie {
    @Inject @Named("lixiaolong")
    private Actor lixiaolong;
    @Inject @Named("zhouxingchi")
    private Actor zhouxingchi;
 
    public void show(){
        lixiaolong.iCanDo();
        zhouxingchi.iCanDo();
    }
}
ActionModule.java
public class ActionModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Actor.class).annotatedWith(Names.named("lixiaolong")).to(LiXiaolong.class);
        bind(Actor.class).annotatedWith(Names.named("zhouxingchi")).to(ZhouXingXing.class);
    }
}
ActionExample.java
public class ActionExample {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new ActionModule());
        ActionMovie actionMovie = injector.getInstance(ActionMovie.class);
        actionMovie.show();
    }
}
输出的当然是你想要的东西
 
分享到:
评论

相关推荐

    Guice教程(Google)

    #### 五、Guice进阶用法 - **绑定**:使用`bind()`方法来显式绑定类型或接口到具体的实现。 - **多绑定**:当需要绑定多个实例时,可以使用`Provides`注解或`@Named`注解。 - **作用域**:Guice支持不同的作用域,...

    GWT入门和进阶

    ### GWT进阶 **1. GWT Compile优化** GWT编译器可以进行多种优化,如死代码删除、类型推断、按需加载等,以减小生成的JavaScript文件大小并提高性能。 **2. Gin Guice集成** Gin是GWT上的轻量级依赖注入框架,基于...

    gwt进阶

    11. **GWT Gin Guice集成**:GWT Gin 基于Google Guice,一个流行的Java依赖注入框架,使得GWT应用可以利用Guice的强大功能。 12. **GWT Super Dev Mode**:这是一种快速开发模式,允许开发者在保存代码后立即看到...

    gradle-git-0.8.0.zip

    标题中的"gradle-git-0.8.0.zip"表明这是一个与...这个项目提供了实践上述技术的实例,对于Java开发者来说,是个不错的学习和进阶资源。通过研究这个项目,不仅可以提升Java编程技能,还能深入了解软件工程的最佳实践。

    GWT完整教程,Word版

    这一部分还将深入讨论GWT的客户端数据管理,包括使用 Gin 和 Guice 进行依赖注入,以及使用GWT的 Place 和 History 模式来实现导航。另外,你将学习到如何利用GWT的Ext GWT(GXT)或SmartGWT等第三方库增强应用的...

    心得.rar心得.rar

    这些文档可能是作者在学习或实践中整理的笔记,涵盖了从基础到进阶的Java知识,以及一些程序员的生活习惯和工具使用经验。 【标签】"心得.rar"进一步确认了这是一个关于Java技术的学习资料集合。 根据【压缩包子...

    Xtext Documentation

    进阶教程涵盖了如何使用Xtend编写代码生成器、创建自定义验证规则等更高级的功能。 ### 参考文档 #### 概述 概述部分详细介绍了Xtext的基本概念、工作原理、配置方式和高级特性。 #### DSL语言开发 这部分详细...

    playframework 框架学习之路 1

    通过这篇学习之路,你将逐步了解如何搭建Play Framework环境,创建第一个应用,理解其核心概念,并可能涉及一些进阶主题,如单元测试、数据库操作和安全控制。深入学习Play Framework将帮助你构建高性能、易于维护的...

    Play Framework应用程序框架 v2.7.9.zip

    3. **可插拔的依赖注入**:支持Guice和Spring作为DI容器,便于组件管理和测试。 4. **模块化结构**:Play Framework支持模块化,允许开发者选择或创建自己的模块来扩展框架功能。 5. **强大的路由系统**:通过简洁的...

    高级JAVA指导

    1. **Ch1 - 基础回顾与进阶**:这部分可能涵盖JAVA基础语法的巩固,如面向对象编程(OOP)的基本概念,包括类、对象、封装、继承和多态,以及异常处理和垃圾回收机制的深入理解。 2. **Ch2 - 高级数据结构与算法**...

    Play Framework Cookbook 代码

    6. **依赖注入(DI)**:Play框架内置了Guice作为默认的依赖注入容器,使得组件的创建和管理更加灵活。通过DI,你可以轻松地替换或扩展应用中的服务。 7. **测试支持**:Play提供了丰富的测试工具,如`play.test`包...

    CXF框架快速起步1

    - **与其他框架的集成**:CXF可以与Spring、Guice等框架无缝集成,方便构建复杂应用。 - **性能优化**:CXF通过缓存、流处理等方式提高服务性能。 ### 二、CXF入门教程 1. **环境准备** - 安装Java Development...

    how to use xtext

    《如何运用Xtext:深入解析...Xtext用户手册涵盖了从入门到进阶的所有方面,是学习和使用Xtext不可或缺的参考资料。通过深入理解Xtext的工作原理和应用实践,开发人员可以更加高效地构建和维护自己的领域特定语言。

Global site tag (gtag.js) - Google Analytics