容器和注入技术

JVM是Java程序唯一认识的操作系统,可执行.class文件。WEB容器是Servlet/JSP唯一认得的HTTP服务器。 
容器说白了就是一个用java写的程序,运行与JVM之上。 
HTTP那些文字性的通信协议,如何变成Servlet/JSP中可用的Java对象,其实就是容器的剖析与转换。 
只要写的Servlet/JSP符合WEB容器的标准规范,Servlet/JSP就可以在各种不同厂商实现的WEB容器上运行,而不用理会底层真正的HTTP服务器是什么。

 

依赖注入(Dependency Injection)是用于实现控制反转(Inversion of Control)的最常见的方式之一。

控制反转用于解耦

1. 为什么需要依赖注入

控制反转用于解耦,解的究竟是谁和谁的耦?这是我在最初了解依赖注入时候产生的第一个问题。

下面我引用Martin Flower在解释介绍注入时使用的一部分代码来说明这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MovieLister {
    private MovieFinder finder;

    public MovieLister() {
        finder = new MovieFinderImpl();
    }
    
    public Movie[] moviesDirectedBy(String arg) {
        List allMovies = finder.findAll();
        for (Iterator it = allMovies.iterator(); it.hasNext();) {
            Movie movie = (Movie) it.next();
            if (!movie.getDirector().equals(arg)) it.remove();
        }
        return (Movie[]) allMovies.toArray(new Movie[allMovies.size()]);
    }
    ...
}

 

1
2
3
public interface MovieFinder {
    List findAll();
}

我们创建了一个名为MovieLister的类来提供需要的电影列表,它moviesDirectedBy方法提供根据导演名来搜索电影的方式。真正负责搜索电影的是实现了MovieFinder接口的MovieFinderImpl,我们的MovieLister类在构造函数中创建了一个MovieFinderImpl的对象。

目前看来,一切都不错。但是,当我们希望修改finder,将finder替换为一种新的实现时(比如为MovieFinder增加一个参数表明Movie数据的来源是哪个数据库),我们不仅需要修改MovieFinderImpl类,还需要修改我们MovieLister中创建MovieFinderImpl的代码。

这就是依赖注入要处理的耦合。这种在MovieLister中创建MovieFinderImpl的方式,使得MovieLister不仅仅依赖于MovieFinder这个接口,它还依赖于MovieListImpl这个实现。 这种在一个类中直接创建另一个类的对象的代码,和硬编码(hard-coded strings)以及硬编码的数字(magic numbers)一样,是一种导致耦合的坏味道,我们可以把这种坏味道称为硬初始化(hard init)

 

posted @ 2019-03-10 22:06  萝卜蹲  阅读(132)  评论(0编辑  收藏  举报