最近在做项目的技术选型,由于项目不想引入庞大的spring家族,所以研究了下guice,一个精巧的ioc框架

官网:https://code.google.com/p/google-guice/

下面是一些简单的例子

首先常见场景,声明一个DAO

public interface BaseDAO {
    public int countUser();
    public String login(String userName);
}

接着是一个Mysql实现

public class MysqlDAO implements BaseDAO {
    @Override
    public int countUser() {
        return 1;
    }
    @Override
    public String login(String userName) {
        return userName + " loggin success ---MYSQL";
    }
}

实现BaseDAO中的方法,登录成功之后返回一条数据。countUser只返回1

在service中如何注入呢,如果是spring2.5,使用resource注解(UserService接口代码略)

public class UserServiceImpl implements UserService {
    @Resource
    private BaseDAO baseDAO;
    public int countUserMethod() {
        return baseDAO.countUser();
    }
    public String loginMethod(String userName) {
        return baseDAO.login(userName);
    }
}

guice和spring类似,提供了一个注解@Inject,把@Resouce换成@Inject就 可以了,

当然guice还提供了其他的注入方式:

构造方法注入:

public class UserServiceImpl implements UserService {
    private final BaseDAO baseDAO;
    // 使用构造方法注入
    @Inject
    public UserServiceImpl(BaseDAO baseDAO) {
        this.baseDAO = baseDAO;
    }
    public int countUserMethod() {
        return baseDAO.countUser();
    }
        ......
}

或者使用方法注入

public class UserServiceImpl implements UserService {
    private BaseDAO baseDAO;
    // 使用方法注入,方法名可以随便起
    @Inject
    public void setDAO(BaseDAO baseDAO) {
        this.baseDAO = baseDAO;
    }
    public int countUserMethod() {
        return baseDAO.countUser();
    }
        ......
}

至于哪种方法最好,引用一段:
三个FrogMan版本都展示了相同的行为:Guice 在构建时注入相应的Vehicle。不过,像 Guice 的作者一样,我更喜欢构造函数注入。下面简单分析这三种方式

  • 构造函数注入很简单。因为 Java 技术能保证构造函数调用,您不用担心出现未初始化的对象 — 不管是不是由 Guice 创建的。您还可以将字段标记为final

  • 字段注入会影响可测试性,特别是将字段标记为private时。这破坏了使用 DI 的主要目的。应该尽量少使用字段注入

  • 方法注入在您不控制类的实例化时很有用。如果您有一个需要某些依赖项的超类,也可以使用方法注入(构造函数注入会使这种情况变得很复杂)。

我个人还是喜欢直接字段注入。。因为需要写的东西少,太懒了。

注入完毕了,测试下。哦不对,想下spring的配置还有好多呢,guice不可能就添加下依赖就没事了吧。当然不行,guice和spring不同的一点就是spring的配置全部放到了xml,而guice的配置全部在代码中,首先你需要建立一个Module实现guice的Module接口或者继承抽象类AbstractModule,我个人建议实现Module接口,继承AbstractModule有写情况还需要添加aop的依赖,尽量简单嘛,我们的BindModule代码如下,绑定DAO和Service的接口到实现

public class BandModule implements Module {
    @Override
    public void configure(Binder binder) {
        // 接口BaseDAO绑定到一个实现MysqlDAO     
        binder.bind(BaseDAO.class).to(MysqlDAO.class);
        // 接口UserService绑定到UserServiceImpl实现        
        binder.bind(UserService.class).to(UserServiceImpl.class);
    }
}

简单吧,实际就是spring里面的那一坨,绑定MysqlDAO这个实现到BaseDAO接口,这里就涉及到了一个问题,binder究竟可以绑定哪些东西呢,可以绑定任意的类吗?可以绑定自己吗?这里就不一一尝试了,直接给出结论:

不可以自己绑定自己,但可以绑定子类到自己,也可以绑定到自己构造出来的实例上。不能绑定多个实例到一个接口上。

配置文件有了,接口和实现也有了,也在service层注入了。可以测试了吧。。看测试代码

public class UserServiceImplTest {
    // 声明module也就是spring里的初始化配置文件
    BandModule bandModule = new BandModule();
    // 获取一个注入器(?也就是spring里面的appli...)
    Injector injector = Guice.createInjector(bandModule);
    // 获取UserService的实例(spring里的xxx=(xxx)act.getBean("xxx");
    UserService userService = injector.getInstance(UserService.class);
    @Test
    public void testCountUserMethod() {
        Assert.assertEquals(userService.countUserMethod(), 1);
    }
    @Test
    public void testLoginMethod() {
    Assert.assertEquals(userService.loginMethod("xxx"),
                "xxx loggin success ---MYSQL");
    }
}

Image Title

ok,测试通过。关于guice的其他功能使用,以后看情况再写

参考:

http://www.ibm.com/developerworks/cn/java/j-guice.html

http://www.blogjava.net/xylz/archive/2009/12/22/306955.html

一些其他资料

http://blog.csdn.net/escaflone/article/details/5694108

http://blog.csdn.net/escaflone/article/details/5696590

http://www.kafka0102.com/2010/06/193.html

http://heuristic-cookbook.appspot.com/Guice%E7%AE%80%E4%BB%8B

Comments
Write a Comment