理解依赖注入,这篇文章写得非常好,结合spring的依赖注入分析的。
http://blog.csdn.net/taijianyu/article/details/2338311/
大体的意思是:
有一个类A,这个类里的属性m(属性是接口类型)需要我们通过构造器或者setter方法传入(比如传入一个B接口实现类的实例,为啥属性或方法的参数类型都是接口类型,因为这样可以传接口不同实现类的实例啊),来为这个类A的该属性m设值。类A有了m属性值,就可以实现很多逻辑了。
在spring框架里,我们不需要自己去向类A的构造器或者setter方法手动传参(甚至不用自己调用这个方法),我们把他们的依赖关系(类A和B接口的一个实现类)写在配置文件中,然后我们调用。
ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml”);
A  a = (A)ctx.getBean(“A类在配置文件中的id名”);
这样我们生成的A的实例中属性m就已经是B接口的那个实现类的实例了。我们根本就不需要自己去手动传入B接口的那个实现类的实例。因为依赖关系已经在配置文件中生成了,那么我们生成实例时,会自动加载。并且因为我们是在配置文件中写的他们的依赖关系,所以如果我们想生成的A的实例的属性m的值是B接口的另外一个实现类实例,我们只需要稍微改下配置文件就可以了,不需要改动java代码。
 
再总结总结上面,就是说我们可以将一个接口类型绑定到一个特定的该接口实现类(这里更精确的说是该接口类型的参数值绑定到了某个特定的该接口实现类的实例上了)上。好处就是在某处代码中需要某个实例时,不用我们自己手动创建(甚至不用传入),而是实现写好了他们的依赖关系,要用的时候就会自动生成了,也就是可以说将某个接口实现类的实例已经注入到 某个类的某个变量中了,相偎相依。
 
guice也可以实现绑定,只是不再使用繁杂的配置文件,下面说说guice:
 
跟前面的例子类似:
  1. class RealBillingService implements BillingService {
  2. private final CreditCardProcessor processor;
  3. private final TransactionLog transactionLog;
  4. @Inject
  5. RealBillingService(CreditCardProcessor processor,
  6. TransactionLog transactionLog) {
  7. this.processor = processor;
  8. this.transactionLog = transactionLog;
  9. }
  10. @Override
  11. public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
  12. ...
  13. }
  14. }
我们实现了BillingService接口(实现里面的chargeOrder()方法),我们在实现的过程中需要CreditCardProcessor和TransactionLog接口实现类的实例,那么我们怎么像spring 那样去给我们这两个CreditCardProcessor和TransactionLog接口类型的变量自动注入实例值呢?是这样的:
我们先自定义一个module,在configure()这个重写方法中进行绑定:
  1. public class BillingModule extends AbstractModule {
  2. @Override
  3. protected void configure() {
  4. /*
  5. * This tells Guice that whenever it sees a dependency on a TransactionLog,
  6. * it should satisfy the dependency using a DatabaseTransactionLog.
  7. */
  8. bind(TransactionLog.class).to(DatabaseTransactionLog.class);
  9. /*
  10. * Similarly, this binding tells Guice that when CreditCardProcessor is used in
  11. * a dependency, that should be satisfied with a PaypalCreditCardProcessor.
  12. */
  13. bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
  14. }
  15. }
 
然后我们在需要使用BillingService接口实现类即RealBillingService实例的地方(我们需要RealBillingService实例中的CreditCardProcessor 接口变量 和  TransactionLog 接口变量都要初始化值,不然没法用,接下来就是做这个事情的,但不是手动直接传参),我们就利用我们创造的BillingModule来生成一个Injector实例:Injector injector = Guice.createInjector(new BillingModule());  
这个injector就具有的这样的功能,即看到标记了@Inject的方法或变量有TransactionLog类型(如果是标记的方法,那么就是方法的参数有这个类型),就弄一个DatabaseTransactionLog类的实例(这里的弄指的是比如,当外界需要获取TransactionLog时(比如一个方法(@Inject标记的方法只能是类的构造方法和setter()方法,不能是其他方法)的参数是TransactionLog类型,就是需要获取),就返回一个DatabaseTransactionLog对象引用(自动返回,不需要手动传参),如果是一个TransactionLog类型的成员变量标记了@inject,那么也是需要获取,那么也会自动给该变量赋值一个DatabaseTransactionLog对象引用
),看到CreditCardProcessor就弄成PaypalCreditCardProcessor。比如这里我们调用:injector.getInstance(RealBillingService.class); 因为RealBillingService java代码中有
  1. @Inject
  2. RealBillingService(CreditCardProcessor processor,
  3. TransactionLog transactionLog) {
  4. this.processor = processor;
  5. this.transactionLog = transactionLog;
  6. }
该方法有一个@inject,那么就会向方法参数中传入:如果是TransactionLog类型,就传入DatabaseTransactionLog这个类的实例。如果是CreditCardProcessor类型,就传入PaypalCreditCardProcessor类的实例。
 这样我们通过调用injector.getInstance(RealBillingService.class)得到的RealBillingService实例中的CreditCardProcessor 接口变量和TransactionLog接口变量已经初始化赋值了,和spring注入机制一样,这里赋值的过程也不需要我们手动的赋值,不需要我们调用构造方法进行传参,按上面的流程走一遍就自动赋值了。
 
上面这样写有一个问题,就是如果我们的RealBillingService这里面所有的标记了@Inject 的方法中和成员变量(假设方法参数里的参数类型和成员变量类型都是TransactionLog类型)需要的TransactionLog接口类型的实现类是不同的,我们上面就不能,因为上面我们绑定的时候,我们bind(TransactionLog.class).to(DatabaseTransactionLog.class); 那么injector看到@Inject下的含TransactionLog方法和变量时,就会传入和赋值DatabaseTransactionLog类型对象。所以这里并不能对于不同的TransactionLog
地方传入或赋值不同的TransactionLog实现类对象。那么我们怎么办呢?我们会使用@Named的方式,具体看代码,很容易理解:
  1. bind(CreditCardProcessor.class)
  2. .annotatedWith(Names.named("Checkout1"))
  3. .to(Checkout1CreditCardProcessor.class);
  4. bind(CreditCardProcessor.class)
  5. .annotatedWith(Names.named("Checkout2"))
  6. .to(Checkout2CreditCardProcessor.class);
 
 
  1. public class RealBillingService implements BillingService {
  2. @Inject
  3. public RealBillingService(@Named("Checkout1") CreditCardProcessor processor,
  4. TransactionLog transactionLog) {
  5. ...
  6. }
  7. @Inject
  8. @Named("Checkout2”)
  9. private CreditCardProcessor processor;
  10. }
 
这样就可以了,相当于在不同的地方做了不同的标记。
 
除了在自己写的module里面的configure()中进行bind()绑定,我们也可以不再这里面绑定,而是在一个接口或父类中直接进行声明。如果用injector对一个java类中的标记了@Inject 的变量和方法进行转换的时候(injector和@inject都不能少,一个是需要injector = Guice.createInjector(new BillingModule()),虽然这时候BillingModule()可以是空,但是还是需要Guice这个角色进行“转换”,因为Guice起着创造(bindBtoA)类B的对象的作用。并且需要@Inject 进行标记包含想要转换的变量的成员变量和方法),如果这个需要转换的类型在创建的时候已经写了如:
@ImplementedBy (SayHello.class)
  1. public interface Talk {
  2. public void sayHello();
  3. }
那么这样就算绑定了,其实和前面的链式bind()那种方式绑定一样的功能,只是绑定的位置不一样。但和链式绑定不同的是它们的优先级,@ImplementedBy实现的是一种default绑定,当同时存在@ImplementedBy和链式绑定时,链式绑定起作用。
 
provider的注入需要的时候再看。

依赖注入和Guice理解的更多相关文章

  1. 记录对依赖注入的小小理解和autofac的简单封装

    首先,我不是一个开发者,只是业余学习者.其次我的文化水平很低,写这个主要是记录一下当前对于这块的理解,因为对于一个低水平 的业余学习者来说,忘记是很平常的事,因为接触.应用的少,现在理解,可能过段时间 ...

  2. C# 一个初学者对 依赖注入 IOC 的理解( 含 Unity 的使用)

    通过 人打电话 来谈谈自己对IOC的理解 版本1.0 public class Person { public AndroidPhone Phone { get; set; } public void ...

  3. 控制反转(IOC) 和依赖注入(DI) 的理解

    1.      IOC(控制反转) inverseof control是spring容器的内核,AOP.声明事务等功能在此基础上开花结果. 2.      通过实例理解IOC概念: 实例:<墨攻 ...

  4. 【NetCore】依赖注入的一些理解与分享

    依赖注入 DI 前言 声明:我是一个菜鸟,此文是自己的理解,可能正确,可能有误.仅供学习参考帮助理解,如果直接拷贝代码使用造成损失概不负责. 相关的文章很多,我就仅在代码层面描述我所理解的依赖注入是个 ...

  5. DI(依赖注入)简单理解 NO1

    依赖注入:目的削减程序的耦合度,达到高内聚/低耦合 常用形式:Interface Driven Design接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等.通过Io ...

  6. 依赖注入的方式测试ArrayList和LinkedList的效率(对依赖注入的再次理解)

    9/20 号再进行学习 在C++中,main函数尽可能的简单,只要调用子函数的一句话就实现了功能. java开发中,controller就相同于是main函数,其他类的方法不在本类中时候, 1.可以用 ...

  7. 对spring控制反转以及依赖注入的理解

    一.说到依赖注入(控制反转),先要理解什么是依赖. Spring 把相互协作的关系称为依赖关系.假如 A组件调用了 B组件的方法,我们可称A组件依赖于 B组件. 二.什么是依赖注入. 在传统的程序设计 ...

  8. 控制反转和依赖注入(对IOC,DI理解+案例)

    理解 控制反转说的官方一点就是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度.其实就是一种设计思想,大概思想就是把设计好的对象交给容器控制,而不是在你内部直接控制. 依赖注入是控制反 ...

  9. 工厂方法模式与IoC/DI控制反转和依赖注入

    IoC——Inversion of Control  控制反转 DI——Dependency Injection   依赖注入 要想理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁? 依赖:谁 ...

随机推荐

  1. 汉澳sinox2014没有黑屏,一个能够依靠的安全避风港

    首先汉澳sinox2014没有验证server,根本就没办法区分正版和盗版 其次汉澳sinox2014安装也没有系列号cdkey等东西,直接安装无干扰 最后汉澳sinox2014不会有黑屏这样的东西. ...

  2. 教你高速入门Excel-宏与VBA(续)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/small_baby01/article/details/24028407 引言         通过 ...

  3. redis的ruby客户端(三)

    1. 介绍 clients这里列出了redis所支持的语言的所有客户端程序,其中就有ruby的.有这么多的客户端,说明要实现redis的客户端是不难的.其实你只要掌握一种语言的socket编程就可以实 ...

  4. smtplib与email模块(实现邮件的发送)

    SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件.HTML邮件以及带附件的邮件. Python对SMTP支持有smtplib和email两个模块,email负责构造邮件, ...

  5. Tomcat 安装、配置与部署

    Tomcat的官方网站:http://tomcat.apache.org/,目前最新版本为7.0. Tomcat下载地址: 1.32位:http://mirrors.tuna.tsinghua.edu ...

  6. go——反射

    反射(reflect)让我们能在运行期探知对象地类型信息和内存结构,这从一定程度上弥补了静态语言在动态行为上地不足.和C数据结构一样,Go对象头部并没有类型指针,通过其自身是无法在运行期获知任何类型相 ...

  7. Phpstorm 换行设置(复制 http://jingyan.baidu.com/article/86fae346b2cb673c49121ad3.html)

    很多时候代码太长超出了屏幕的宽度,默认情况下没有自动换行的,我们需要把光标往后挪,才能看到后面代码,显得略为蛋疼,我个人比较喜欢能够自动换行. 下面就说下Phpstorm里如何默认开启自动换行(use ...

  8. Linux系统配置VI或VIM的技巧

    Linux系统配置VI或VIM的技巧作者:IT专家网论坛出处:IT专家网论坛2008-10-28 11:08配置VI和VIM的颜色显示,使它能够高亮度显示一些特别的单词,这对编写程序很有用⋯⋯ 1.V ...

  9. vue-cli中config目录下的index.js文件详解

    vue-cli脚手架工具config目录下的index.js解析 转载自:http://www.cnblogs.com/ye-hcj/p/7077796.html // see http://vuej ...

  10. [Android]AndFix使用说明

    AndFix使用说明 AndFix,全称是Android hot-fix.是阿里开源的一个热补丁框架,允许APP在不重新发布版本的情况下修复线上的bug.支持Android 2.3 到 6.0,并且支 ...