java中依赖注入和服务定位器详解

在Java社区有一股使用轻量级容器来帮助组装不同项目的组件、集成到一个有凝聚力的应用程序的热潮。

这些底层容器有一种普遍的模式去展示他们如何装配组件,他们提出一个概念,名为“控制反转”(Inversion of Control)。

接下来我们深入挖掘下这个模式在“依赖注入”(Dependency Injection)怎么运作的,并且跟服务定位器进行对比。

组件和服务

我说的使用组件意味着,很多软件能自由的使用它,不需改变,因为这个组件已经不受作者的控制。

当我们在外部系统中使用的时候,服务类似组件。

唯一的不同点是我期望在本地使用组件(eg jar file,assembly,dll,or source inport)。

服务通过远程接口来远程调用,可以同步或者异步操作。(eg web service, messaging system, RPC, or socket.)

依赖注入

injector

分为三种类型:构造器注入、setter注入、接口注入。

1 构造器:

class MovieLister...

  public MovieLister(MovieFinder finder) {
      this.finder = finder;      
  }
2 setter:

class MovieLister...

  private MovieFinder finder;
public void setFinder(MovieFinder finder) {
  this.finder = finder;
}
setter的xml配置

<beans>
    <bean id="MovieLister" class="spring.MovieLister">
        <property name="finder">
            <ref local="MovieFinder"/>
        </property>
    </bean>
</beans>
3 接口:

public interface InjectFinder {
    void injectFinder(MovieFinder finder);
}

class MovieLister implements InjectFinder

  public void injectFinder(MovieFinder finder) {
      this.finder = finder;
  }

服务定位器

依赖注入最主要的好处是移除了MovieLister和MovieFinder的implementation(实现)上的依赖。但这并不是唯一的方法,另一种方法是服务定位器。

class ServiceLocator...

  private static ServiceLocator soleInstance;
  public static void load(ServiceLocator arg) {
      soleInstance = arg;
  }
  private Map services = new HashMap();
  public static Object getService(String key){
      return soleInstance.services.get(key);
  }
  public void loadService (String key, Object service) {
      services.put(key, service);
  }

class Tester...

  private void configure() {
      ServiceLocator locator = new ServiceLocator();
      locator.loadService("MovieFinder", new ColonMovieFinder("movies1.txt"));
      ServiceLocator.load(locator);
  }

class MovieLister...

  MovieFinder finder = (MovieFinder) ServiceLocator.getService("MovieFinder");
依赖注入对于服务定位器来说是一种备选方案。服务定位器因为它的直接行为而有些许优势,但是如果你在很多应用中创建classes的时候,依赖注入是一种更好的选择。

思考:

1.Service Locator vs Dependency Injection

2.Constructor versus Setter Injection

3.Code or configuration files

4.Separating Configuration from Use

时间: 2024-09-24 00:37:05

java中依赖注入和服务定位器详解的相关文章

java中哈希表及其应用详解_java

哈希表也称为散列表,是用来存储群体对象的集合类结构. 什么是哈希表 数组和向量都可以存储对象,但对象的存储位置是随机的,也就是说对象本身与其存储位置之间没有必然的联系.当要查找一个对象时,只能以某种顺序(如顺序查找或二分查找)与各个元素进行比较,当数组或向量中的元素数量很多时,查找的效率会明显的降低. 一种有效的存储方式,是不与其他元素进行比较,一次存取便能得到所需要的记录.这就需要在对象的存储位置和对象的关键属性(设为 k)之间建立一个特定的对应关系(设为 f),使每个对象与一个唯一的存储位置

JAVA中的异常与错误处理详解

  异常与错误: 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它.Java中使用异常类来表示异常,不同的异常类代表了不同的异常.但是在Java中所有的异常都有一个基类,叫做Exception. 错误: 它指的是一个合理的应用程序不能截获的严重的问题.大多数都是反常的情况.错误是VM的一个故障(虽然它可以是任何系统级的服务

JAVA中static方法的用法实例详解_java

本文实例讲述了JAVA中static方法的用法.分享给大家供大家参考,具体如下: static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享.只要这个类被加载,Java虚拟机就能根据类名在运行时数据区或者方法区内找到他们.因此,static对象可以在它的任何对象创建之前访

Java中自然排序和比较器排序详解_java

前言 当指执行插入排序.希尔排序.归并排序等算法时,比较两个对象"大小"的比较操作.我们很容易理解整型的 i>j 这样的比较方式,但当我们对多个对象进行排序时,如何比较两个对象的"大小"呢?这样的比较 stu1 > stu2 显然是不可能通过编译的.为了解决如何比较两个对象大小的问题,JDK提供了两个接口 java.lang.Comparable 和 java.util.Comparator . 一.自然排序:java.lang.Comparable C

JAVA中的final关键字用法实例详解_java

本文实例讲述了JAVA中的final关键字用法.分享给大家供大家参考,具体如下: 根据上下文环境,java的关键字final也存在着细微的区别,但通常指的是"这是无法改变的."不想改变的理由有两种:一种是效率,另一种是设计.由于两个原因相差很远,所以关键子final可能被误用. 接下来介绍一下使用到final的三中情况:数据,方法,类 final数据 许多编程语言都有某种方法,来向编译器告知一块数据是恒定不变的.有时数据的恒定不变是很有用的,例如: 1. 一个编译时恒定不变的常量 2.

Java中FilterInputStream和FilterOutputStream的用法详解_java

FilterInputStream FilterInputStream 的作用是用来"封装其它的输入流,并为它们提供额外的功能".它的常用的子类有BufferedInputStream和DataInputStream. BufferedInputStream的作用就是为"输入流提供缓冲功能,以及mark()和reset()功能". DataInputStream 是用来装饰其它输入流,它"允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类

java中Struts2文件上传问题详解_java

首先是网页部分,upload_file.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML> <html> <head> <title>Upload File</title> </head> <body> <form act

Java中堆内存和栈内存详解

Java把内存分成两种,一种叫做栈内存,一种叫做堆内存. 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用. 堆内存用于存放由new创建的对象和数组.在堆中分配的内存,由java虚拟机自动垃圾回收器来管理.在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存

java集合——Java中的equals和hashCode方法详解_java

Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这两个方法,今天就来介绍一些这两个方法的作用. equals()和hashCode()方法是用来在同一类中做比较用的,尤其是在容器里如set存放同一类对象时用来判断放入的对象是否重复. 这里我们首先要明白一个问题: equals()相等的两个对象,hashcode()一定相等,equals()不相等的两个对象,却并不能证明他们的hashcode()不相等.换