解读超轻量级DI容器-Guice与Spring框架的区别【转载】
依赖注入,DI(Dependency Injection),它的作用自然不必多说,提及DI容器,例如spring,picoContainer,EJB容器等等,近日,google诞生了更轻巧的DI容器……Guice!
废话不多讲了,先看看Guice是如何实现注入的吧。
定义一个简单的service接口和它的实现吧:
void myMethod();
}
public class MyServiceImpl implements MyService {
public void myMethod() {
System.out.println("Hello,World!");
}
}
以上是最普通的接口和其实现,没什么可说的。
定义一个测试类,这个类里边包括service对象的一个引用,这个对象是需要Guice进行注入的
public class Client {
MyService service;
@Inject //告诉容器,这里的service对象的引用,需要进行注入
void setService(MyService service) { //这里的方法名字可以任意定义
this.service = service;
}
public void myMethod() {
service.myMethod();
}
}
这里除了加了一个@Inject,和Spring的配置没有任何的区别,@Inject,是表示对容器说,这里的service需要注射,等到运行的时候,容器会拿来一个实例给service,完成注射的过程。
定义Guice的Module文件 告诉容器如何进行注入
import com.google.inject.Module;
import com.google.inject.Scopes;
public class MyModule implements Module {
public void configure(Binder binder) { binder.bind(MyService.class).to(MyServiceImpl.class).in(Scopes.SINGLETON);
// 这句代码的意思是说:运行时动态的将MyServiceImpl对象赋给MyService定义的对象,而且这个对象是单例的。
}
}
创建测试类
import com.google.inject.Injector;
public class Test {
public static void main(String[] args) {
MyModule module = new MyModule();// 定义注射规则
Injector injector = Guice.createInjector(module);// 根据注射规则,生成注射者
Client client = new Client();
injector.injectMembers(client);// 注射者将需要注射的bean,按照规则,把client这个客户端进行注射
client.myMethod();
}
}
运行测试类,控制台输出:Hello,World!
完成注入过程
下面看看Guice还有哪些其它的使用特性。
1,如果在实现你确定MyService定义的对象,就要被注射为MyServiceImpl而不是其它的实现类的话,可以在MyService接口加上@ImplementedBy(MyServiceImpl.class)
@ImplementedBy(MyServiceImpl.class)
//我总觉得这样有点背离了依赖注入的初衷了
public interface MyService {
void myMethod();
}
这样的话,在MyModule里的configure方法中就可以不加任何东西,容器就会自动注射给MyServiceImpl对象。
2,可以对Field进行注解式注入
在Client.java中也可以把这个@Inject标注在MyService service;的前边,如:@Inject MyService service;
3,可使用自定义Annotation标注。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.FIELD, ElementType.PARAMETER })
@BindingAnnotation
public @interface MyInterface {
}
那么Client.java需要改为
import com.google.inject.Inject;
public class Client {
@Inject @MyInterface MyService service;
void setService(MyService service) { // 这里的方法名字可以任意定义
this.service = service;
}
public void myMethod() {
service.myMethod();
}
}
MyModule.java中的configure方法内容需改为:
binder.bind(MyService.class).annotatedWith(MyInterface.class).to(
MyServiceImpl.class).in(Scopes.SINGLETON);
意思是说对于标注为MyInterface的MyService定义的对象进行注入
进行Annotation标注的成员(Field,method,argument等)进行自定义Annotation标注,该成员既拥有该属性,可以在运行,根据这些成员的不同属性,做一些不同的事情 例如:spring的AspectJ,xdoclet等都是如此。
下边是我做了一下对比
Spring | Guice | |
使用XML | 使用将类与类之间的关系隔离到xml中,由容器负责注入被调用的对象,因此叫做依赖注入 | 不使用xml,将类与类之间的关系隔离到Module中,声名何处需要注入,由容器根据Module里的描述,注入被调用的对象。 |
使用Annotation | 使用 支持自定义Annotation标注,对于相同的接口定义的对象引用,为它们标注上不同的自定义Annotation注释,就可以达到同一个类里边的同一个接口的引用,注射给不同的实现,在Module里用标注做区分,灵活性大大增加。 使用Annotation也未必是好事,范型等新特性也未必是好事,目前大多的服务器均不支持jdk1.5,wls要9以前才支持,而目前的客户由于价格原因也很少选用wls9的,至少我们做过的项目中都没有。功能再强,客户不需要,何用? |
|
运行效率 | 装载spring配置文件时,需解析xml,效率低,getBean效率也不高,不过使用环境不会涉及到getBean,只有生产环境的时候会用到getBean,在装载spring应用程序的时候,已经完成全部的注射,所以这个低效率的问题不是问题。 | 使用Annotation,cglib, 效率高与spring最明显的一个区别,spring是在装载spring配置文件的时候把该注入的地方都注入完,而Guice呢,则是在使用的时候去注射,运行效率和灵活性高。 |
类耦合度 | 耦合度低,强调类非侵入,以外部化的方式处理依赖关系,类里边是很干净的,在配置文件里做文章,对类的依赖性极低。 | 高,代码级的标注,DI标记@inject侵入代码中,耦合到了类层面上来,何止侵入,简直侵略,代码耦合了过多guice的东西,大大背离了依赖注入的初衷,对于代码的可维护性,可读性均不利 |
类编写时 | 需要编写xml,配置Bean,配置注入 | 只需声明为@inject,等着被注入, 最后在统一的Module里声明注入方式 |
仅支持IOC | 否,spring目前已经涉猎很多部分 | 是,目前仅仅是个DI容器 |
是否易于代码重构 | 统一的xml配置入口,更改容易 | 配置工作是在Module里进行,和spring异曲同功 |
支持多种注入方式 | 构造器,setter方法 | Field,构造器,setter方法 |
灵活性 |
1,如果同一个接口定义的引用需要注入不同的实现,就要编写不同的Module,烦琐 2,动态注入 如果你想注射的一个实现,你还未知呢,怎么办呢,spring是没办法,事先在配置文件里写死的,而Guice就可以做到,就是说我想注射的这个对象我还不知道注射给谁呢,是在运行时才能得到的的这个接口的实现,所以这就大大提高了依赖注射的灵活性,动态注射。 |
|
与现有框架集成度 | 1, 高,众多现有优秀的框架(如struts1.x等)均提供了spring的集成入口,而且spring已经不仅仅是依赖注入,包括众多方面。 2, Spring也提供了对Hibernate等的集成,可大大简化开发难度。 3, 提供对于orm,rmi,webservice等等接口众多,体系庞大。 |
1,可以与现有框架集成,不过仅仅依靠一个效率稍高的DI,就想取代spring的地位,有点难度。 |
配置复杂度 | 在xml中定位类与类之间的关系,难度低 | 代码级定位类与类之间的关系,难度稍高 |
再借斧子的例子说一说spring与guice的区别
看下边对于不同社会形态下一个人(java对象,调用者)需要一把斧子(java对象,被调用者)的例子:
(1),原始社会时,劳动社会基本没有分工,需要斧子的人(调用者)只好自己去磨一把斧子,每个人拥有自己的斧子,如果把大家的石斧改为铁斧,需要每个人都要学会磨铁斧的本领,工作效率极低。
对应Java里的情形是:java程序里的调用者new一个被调用者的实例。类耦合度极高,修改维护烦琐,效率极低。
(2),工业社会时,工厂出现,斧子不再由普通人完成,而由工厂生产,当人们需要斧子的时候,可以到工厂购买斧子,无需关心斧子是怎么制造出来的,如果废弃铁斧为钢斧,只需改变工厂的制造工艺即可,制作工艺是工厂决定的,工厂生产什么斧子,工人们就得用什么斧子。
对应的Java里的情形是:Java程序的调用者可以以来简单工厂创建被调用者,变化点被隔离到了简单工厂里,虽然耦合度降低,但是调用者会和工厂耦合,而且需要定位自己的工厂。
(3)近代工业社会,工厂蓬勃发展,人们需要什么斧子,只需要提供一个斧子图形,商家会按照你提供的图形将你的斧子订做好,送上门。
对应Java里的情形:spring的依赖注入
(4)进入按需要分配社会,信息进入现代化,人们不再去工厂购买斧子,不再拘泥于需要什么斧子事先画好什么样的图形,只需要打个电话,描述一下需要什么类型的斧子,或许想打造一个物美价廉的斧子,商家会根据市场零件的价格,计算出最优制作工艺,打造最适合的斧子送过来,更加信息化,更加人性化。
对应Java里的情形:基于描述的注入,动态的,灵活简单的注入,如:Guice。
对于该不该使用Guice,我想也是仁者见仁,智者见智,就象好多论坛里动不动有人会在那里讨论到底学Java还是学.net或者是使用eclipse还是Jbuilder的这类无聊话题,适合和满足项目需求的,又能省工省力简单的完成工作的,就是最好的。
本文转自:http://www.blogjava.net/lixuehui/articles/Guice.html
解读超轻量级DI容器-Guice与Spring框架的区别【转载】的更多相关文章
- Guice与Spring框架的区别
2007-4-23 再借斧子的例子说一说spring与guice的区别 看下边对于不同社会形态下一个人(java对象,调用者)需要一把斧子(java对象,被调用者)的例子: (1),原始社会 ...
- Spring 系列: Spring 框架简介(转载)
Spring 系列: Spring 框架简介 http://www.ibm.com/developerworks/cn/java/wa-spring1/ Spring AOP 和 IOC 容器入门 在 ...
- Spring MVC -- Spring框架入门(IoC和DI)
Spring MVC是Spring框架中用于Web应用开发的一个模块.Spring MVC的MVC是Model-View-Controller的缩写.它是一个广泛应用于图像化用户交互开发中的设计模式, ...
- Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)
去年通过实际框架代码的阅读,以及结合<Spring源码深度解析>和<Spring技术内幕>的阅读,对Spring框架内Bean模块有了一个整体性的认识.对此进行的总结性整理和回 ...
- Java开发工程师(Web方向) - 04.Spring框架 - 第2章.IoC容器
第2章.IoC容器 IoC容器概述 abstract: 介绍IoC和bean的用处和使用 IoC容器处于整个Spring框架中比较核心的位置:Core Container: Beans, Core, ...
- spring框架:(一) 技术说明(技术介绍,技术优势以及发展史等)
一.技术说明(技术介绍,技术优势以及发展史等) 1.1.什么是spring 1.2.spring由来(发展历程) 1.3.spring核心 1.4.spring优点 1.5.spring体系结构 1. ...
- Spring 系列: Spring 框架简介 -7个部分
Spring 系列: Spring 框架简介 Spring AOP 和 IOC 容器入门 在这由三部分组成的介绍 Spring 框架的系列文章的第一期中,将开始学习如何用 Spring 技术构建轻量级 ...
- Spring框架简单介绍
原文地址: http://my.oschina.net/myriads/blog/37922 1.使用框架的意义与Spring的主要内容 随着软件结构的日益庞大,软件模块化趋势出现,软件开发也须要多 ...
- 【Java】关于Spring框架的总结 (一)
本文总结一些关于Spring框架的理解,注意点及基础操作.如果有不对的地方,欢迎批评和建议.大家一起努力吧! Spring 框架简介 Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创 ...
随机推荐
- 在VM克隆CENTOS以后,网卡的处理过程
会发现克隆CENTOS以后,网卡eth0无法启动.处理步骤如下:1. vi /etc/sysconfig/network-scripts/ifcfg-eth0删除HWADDR地址那行删除UUID的那行 ...
- Linux进程与线程概述
进程与线程 实现方式的区别:进程是资源分配的基本单位,线程是调度的基本单位. 为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间.不同的线程可以存取内存中的同 ...
- 图文并茂 RAID 技术全解 – RAID0、RAID1、RAID5、RAID100
RAID 技术相信大家都有接触过,尤其是服务器运维人员,RAID 概念很多,有时候会概念混淆.这篇文章为网络转载,写得相当不错,它对 RAID 技术的概念特征.基本原理.关键技术.各种等级和发展现状进 ...
- solr查询空值、null、不存在的字段的方法
正常情况下我们都是按有值的方式去搜索,但是有时候有一些字段为null,solr中就没有存储进去,我们怎么获取这个字段不存在为条件的搜索结果了,我们只需要在搜索字段前加上负号,如下图 摘要: Solr的 ...
- node进阶之用流实现上传文件
内容: 1.文件上传基础 2.node文件处理机制 3.用流实现文件上传 1.文件上传基础 前端代码: <form action="localhost:8080/" meth ...
- PL/SQL 的一些用法
变量的声明,赋值,打印(declare是pl/sql里面的用法 variable是sql*plus里面的用法,variable相当于一个sql*plus环境的全局变量,declare里定义的是pl/s ...
- 手贱!使用django,在数据库直接删除了表
莫名其妙的错误. 删除了migreation文件,并且更换了数据库. 1.直接makemigrations + migrate error: no change ?? WTF 2.makemi ...
- leetcode100
/** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNo ...
- AS3 巧用事件api简化鼠标拖动流程
拖动,按照一般人的定义,拖动就是鼠标按下的时候移动鼠标,这里面有三个过程,分别是按下.移动鼠标和弹起.以stage为例,大家的实现步骤通常如下:(PS:此处不讨论startDrag和stopDrag ...
- 文字折行不折行 css
white-space : 1. normal 默认值 ,文字自动换行. 2. pre 使用<pre>标签形式,表示元素. * ...