看了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());
}
}
}
最终的运行结果如下:
附上整个项目的结构