基于Spring的控制反转与依赖注入的简单实现

看了Martin Fowler大牛的关于IOC与DI的文章,就自己动手基于Spring实现了一下。
这里的MovieFinderImpl类其实就是后面的ColonMovieFinder类,总体的思想,就是把MovieFinderImpl注入到MovieLister中,而这些都由Assembler来完成,具体指Spring中的IoC容器。
这里写图片描述

1.在Idea中新建一个Maven项目

2.配置pom.xml文件,主要是Spring和slf4j日志的配置,Spring框架支持setter的依赖注入,而且开发者更偏好这种,而不是构造函数方式的依赖注入

The Spring framework is a wide ranging framework for enterprise Java development. It includes abstraction layers for transactions, persistence frameworks, web application development and JDBC. Like PicoContainer it supports both constructor and setter injection, but its developers tend to prefer setter injection. —— Martin Fowler

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>xqcv</groupId>
    <artifactId>xqcv</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java-version>1.8</java-version>
        <org.springframework-version>4.1.0.RELEASE</org.springframework-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
    </properties>
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</project>

3.编写Movie.java文件

public class Movie {
  private int id;
  private String director;
  private String title;

  public Movie(int id, String director, String title) {
    this.id = id;
    this.director = director;
    this.title = title;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getDirector() {
    return director;
  }

  public void setDirector(String director) {
    this.director = director;
  }

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  @Override
  public String toString() {
    return "Movie{" +
            "id=" + id +
            ", director='" + director + '\'' +
            ", title='" + title + '\'' +
            '}';
  }
}

4.编写MovieFinder接口

import java.util.List;

public interface MovieFinder {
  List findAll();
}

5.编写ColonMovieFinder类,需要实现findAll函数,即从txt文件中读取出所有电影的信息

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class ColonMovieFinder implements MovieFinder {
  private String filename;

  public void setFilename(String filename) {
    this.filename = filename;
  }

  private void readTxtToList(List<Movie> movies) {
    File file = new File(Thread.currentThread().getContextClassLoader().getResource(filename).getPath());
    InputStreamReader reader;
    try {
      reader = new InputStreamReader(new FileInputStream(file));
      BufferedReader br = new BufferedReader(reader);
      String line;
      while ((line = br.readLine()) != null) {
        movies.add(new Movie(Integer.valueOf(line.split("\t")[0]),
                line.split("\t")[1], line.split("\t")[2]));
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public List findAll() {
    List<Movie> movies = new ArrayList<Movie>();
    readTxtToList(movies);
    return movies;
  }
}

6.这是movies1.txt文件,每一行是一条电影的信息

1   Sergio Leone    AAA
2   Sergio Leone    BBB
3   Jake Roller CCC
4   Howard Td   DDD

7.实现MovieLister类,MovieFinder即为MovieLister的依赖

import java.util.Iterator;
import java.util.List;

public class MovieLister {
  private MovieFinder finder;

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

  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()]);
  }
}

8.编写spring.xml文件,核心在这个地方,所谓IoC Container的配置指的就是这个地方,Spring底层实现好了,所有只需要在这里配置,就不用在代码中手工写new了

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--把ColonMovieFinder注入到MovieLister类-->
    <beans:bean id="MovieFinder" class="ColonMovieFinder">
        <beans:property name="filename">
            <beans:value>movies1.txt</beans:value>
        </beans:property>
    </beans:bean>

    <beans:bean id="MovieLister" class="MovieLister">
        <beans:property name="finder">
            <beans:ref bean="MovieFinder"/>
        </beans:property>
    </beans:bean>

</beans:beans>

9.编写最后的测试文件

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Test {
  public static void main(String[] args) {
    ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:spring.xml");

    //如果没有spring.xml里面的注入配置,就需要这样写,所以这样代码就复杂了许多
//    ColonMovieFinder finder = new ColonMovieFinder();
//    finder.setFilename("movies1.txt");
//    MovieLister lister = new MovieLister();
//    lister.setFinder(finder);

    MovieLister lister = (MovieLister) ctx.getBean("MovieLister");
    Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
    for (Movie m : movies) {
      System.out.println(m.toString());
    }
  }
}

最终的运行结果如下:
这里写图片描述

附上整个项目的结构
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qxconverse/article/details/80369041