使用guice进行依赖注入与模块化系统

原创 2017年06月25日 11:59:36

一、Guice介绍
1,Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IOC)。Guice非常小而且快。Guice是类型安全的,它能够对构造函数,属性,方法(包含任意个参数的任意方法,而不仅仅是setter方法)进行注入。
2,elasticsearch是直接把guice的源码放到自己的包内(es把很多开源项目的代码都直接集成到自己项目中,省得依赖一堆的jar包,也使es的jar包达到差不多10M),在org.elasticsearch.common.inject目录下。

二、Module依赖注册
Guice提供依赖配置类,需要继承至AbstractModule,实现configure方法。在configure方法中我们可以用Binder配置依赖。

Binder利用链式形成一套独具语义的DSL,如:

基本配置:binder.bind(serviceClass).to(implClass).in(Scopes.[SINGLETON | NO_SCOPE]);
无base类、接口配置:binder.bind(implClass).in(Scopes.[SINGLETON | NO_SCOPE]);
service实例配置:binder.bind(serviceClass).toInstance(servieInstance).in(Scopes.[SINGLETON | NO_SCOPE]);
多个实例按名注入:binder.bind(serviceClass).annotatedWith(Names.named(“name”)).to(implClass).in(Scopes.[SINGLETON | NO_SCOPE]);
运行时注入:利用@Provides标注注入方法,相当于spring的@Bean。
@ImplementedBy:或者在实现接口之上标注@ImplementedBy指定其实现类。这种方式有点反OO设计,抽象不该知道其实现类。

三、如何使用Guice进行依赖注入

public interface WatchVideoService {

    public void buyVip();

}
public interface SearchService {

    public void printSource();
}
import com.google.inject.Inject;
import com.sohu.search.guice.service.SearchService;
import com.sohu.search.guice.service.WatchVideoService;

/**
 * Created by jiangtao on 17-6-19.
 */
public class MobileSearchServiceImpl implements SearchService {


    private WatchVideoService watchVideoService;

    //使用@inject guice会扫描inject注释,并对方法中出现的参数实例寻找对应注册的实例进行初始化。
    @Inject
    public MobileSearchServiceImpl(WatchVideoService watchVideoService){
        this.watchVideoService = watchVideoService;
    }


    @Override
    public void printSource() {
        watchVideoService.buyVip();
        System.out.println("移动端不出UGC视频");
    }
}

import javax.inject.Inject;

/**
 * Created by jiangtao on 17-6-19.
 */
public class PCSearchServiceImpl implements SearchService {



    private WatchVideoService watchVideoService;

    /**
     * 使用@inject  guice会扫描inject注释,并对方法中出现的参数实例寻找对应注册的实例进行初始化。
     * @param watchVideoService
     */
    @Inject
    public PCSearchServiceImpl(WatchVideoService watchVideoService){
        this.watchVideoService = watchVideoService;
    }

    @Override
    public void printSource() {
        watchVideoService.buyVip();
        System.out.println("pc端出ugc视频");
    }
}

/**
 * Created by jiangtao on 17-6-20.
 */
public class WatchVideoServiceImpl implements WatchVideoService {

    @Override
    public void buyVip() {
        System.out.println("请购买会员,再观看视频");
    }

}
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Provides;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.sohu.search.guice.service.SearchService;
import com.sohu.search.guice.service.WatchVideoService;
import com.sohu.search.guice.service.impl.MobileSearchServiceImpl;
import com.sohu.search.guice.service.impl.PCSearchServiceImpl;
import com.sohu.search.guice.service.impl.WatchVideoServiceImpl;

import java.util.List;

import static com.google.common.collect.ImmutableList.of;

/**
 * Created by jiangtao on 17-6-19.
 */
public class SearchModule extends AbstractModule {


    /**
     * 每个module里面都有一个方法configure()用于将对象和实现类作绑定
     * Module(模块)是Guice用来管理一组绑定关系的地方。
     * 自定义模块需要继承AbstractModule类并覆盖configure方法,在configure方法中设置绑定关系。
     * Guice创建时可使用多个模块,则注入器可以注入多个模块中指定的绑定关系。
     */
    @Override
    protected void configure() {
        final Binder binder = binder();
        /**
         * 一个接口多个实现。
         */
        binder.bind(SearchService.class).annotatedWith(Names.named("pcSearch")).to(PCSearchServiceImpl.class);
        binder.bind(SearchService.class).annotatedWith(Names.named("mobileSearch")).to(MobileSearchServiceImpl.class);
        /**
         * 一个接口只有一个实现。
         * bind接口将接口跟具体实现类绑定。
         */

        //使用asEagerSingleton方法,强制Guice立即实例化类并注入:饿汉模式。
        binder.bind(WatchVideoService.class).to(WatchVideoServiceImpl.class).asEagerSingleton();
    }


    /**
     * @Provides标注注入方法来运行时注入
     * @param pcService
     * @param mobileService
     * @return
     */
    @Provides
    public SearchService getSearchService(@Named("pcSearch") SearchService pcService,
                                                  @Named("mobileSearch") SearchService mobileService) {

        if(Math.random()*10 > 5){
            return pcService;
        }
        return mobileService;
    }

}
/**
 * Created by jiangtao on 17-6-19.
 */
public class SearchModuleTest {

    private Injector injector;

   //使用 Injector 引导应用程序。
    @Before
    public void setUp() throws Exception {
        injector = Guice.createInjector(new SearchModule());
    }


    @Test
    public void print() throws Exception {

        final SearchService pcService = injector.getInstance(PCSearchServiceImpl.class);

        pcService.printSource();

        /**
         *
         */
        final SearchService mobileService = injector.getInstance(MobileSearchServiceImpl.class);

        mobileService.printSource();

        /**
         * 使用@provides进行动态注入
         */
        final SearchService searchService = injector.getInstance(new Key<SearchService>(){});

        searchService.printSource();
    }


    /**
     * 是否为单例
     * result:为单例
     * @throws Exception
     */
    @Test
    public void should_be_singleton_for_one_without_interface_bean() throws Exception {
        //when
        final WatchVideoService first = injector.getInstance(WatchVideoService.class);
        final WatchVideoService second = injector.getInstance(WatchVideoService.class);
        //then
        assertThat(first, is(sameInstance(second)));
    }
}

四、参考文档:
1,https://www.ibm.com/developerworks/cn/java/j-guice.html (ibm关于guice 2.0讲解)
2,https://github.com/google/guice/wiki/GettingStarted (guice官方wiki)

相关文章推荐

深入剖析Guice(Google依赖注入框架)

众所周知的依赖注入框架Spring,但还有一个性能好且轻量的框架Guice,Guice来自Google,且Google的很多产品都是使用的Guice...

Google Guice 依赖注入框架:简明教程

Guice是一个轻量级的依赖注入框架。用于对象之间的依赖的注入。 本文的所有例子基于Guice 4.0 Guice的使用: Guice的使用涉及接口,接口的实现类,接口与其实现类...

Guice 学习(二)构造器注入(Constructor Inject)

为了演示下面的支持多参数的构造函数注入,我在这里写了2个接口和其实现类。注意事项写在了程序注释里面。 1、接口 (interface)/* * Creation : 2015年6月30日 */ p...

Jackson第三篇【ObjectMapper的并发编程】

前两篇文章咱们一起学习了一下,Jackson的基本使用方法还记得第一篇文章我获得一个ObjectMapper对象整得那么麻烦 。还用用单例模式来获取为什么不直接new?先看一个数据吧。    我...

elasticsearch源码分析之使用Guice进行依赖注入与模块化系统

elasticsearch使用google开源的依赖注入框架guice,这个项目号称比spring快100倍,具体性能没有测试过,不过由于其代码比较简洁,比spring快很有可能,是不是快那么多就不知...
  • psiitoy
  • psiitoy
  • 2017年06月15日 21:35
  • 148

ElasticSearch源码分析之一:使用Guice进行依赖注入与模块化系统

1. 使用Guice进行依赖注入与模块化系统 elasticsearch使用google开源的依赖注入框架guice,这个项目号称比spring快100倍,具体性能没有测试过,不过由于其代码比较简洁...

Elasticsearch源码分析之一——使用Guice进行依赖注入与模块化系统

elasticsearch使用google开源的依赖注入框架guice,这个项目号称比spring快100倍,具体性能没有测试过,不过由于其代码比较简洁,比spring快很有可能,是不是快那么多就不知...

Elasticsearch源码分析之一——使用Guice进行依赖注入与模块化系统

elasticsearch使用google开源的依赖注入框架guice,这个项目号称比spring快100倍,具体性能没有测试过,不过由于其代码比较简洁,比spring快很有可能,是不是快那么多就不知...

AngularJS 模块化与依赖注入

AngularJS使用模块化的组织方式,和依赖注入的设计。这使得模块之间耦合度较低,模块更容易复用。同时支持声明式的编程风格。 在你创建Angular Module 或者 Service 之前,首...

guice超轻量级依赖注入

  • 2011年08月09日 23:31
  • 866KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用guice进行依赖注入与模块化系统
举报原因:
原因补充:

(最多只允许输入30个字)