最近在做项目的技术选型,由于项目不想引入庞大的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");
}
}
ok,测试通过。关于guice的其他功能使用,以后看情况再写
参考:
一些其他资料