还是先上一个简单的代码段再来说明问题:
package com.akwolf.spring.common;
public class CommonSimple {
public int compute(int i, int j) {
return i + j;
}
}
package com.akwolf.spring.common;
public class UserSimple {
public static void main(String[] args) {
CommonSimple commonSimple = new CommonSimple() ;
System.out.println(commonSimple.compute(5, 8));
}
}
通常情况下,我们要使用一个类就是在需要的地方直接采用new关键字,创建对象然后调用方法,一切看上去so perfect,代码也运行的很正常,但在想长远一点,若以后需求发生改变,main方法中要使用乘法进行进行计算,那就得修改代码,创建有乘法方法的对象,少量的代码,没问题,我挨着手动的改,当代码量巨大的时候,嘿嘿,,噩梦开始了。另一个方面,好的OO编程思想是要符合开闭原则,即对修改关闭,对拓展开放。要降低耦合................ ,反正就一大堆啦,,这个时候引入spring看一下。
一、Spring的主要思想。我就不罗嗦了,控制反转(IOC、DI),面向接口编程,google一下讲解的很多。
二、搭建一个Spring的开发环境。
1、对于没有特殊需求加入spring.jar和commons-logging.jar就已足够,使用eclipse时build path一下就ok。
2、在src目录下建一个beans.xml ,对要使用的到类,进行管理,,这就降低了耦合,在使用的使用不在使用new关键字了,贴一下配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- 初始化sample实现类 -->
<bean
id="sample"
class="com.akwolf.spring.impl.SampleImpl" />
</beans>
这时再来看一下,再怎么使用(在Junit中编写的代码,自己测试时要引入junit的库)
private static ApplicationContext context ;
@BeforeClass
public static void init(){
context = new ClassPathXmlApplicationContext("beans.xml") ;
}
@Test
public void testCompute() {
Sample sample = (Sample) context.getBean("sample") ;
System.out.println(sample.compute(5, 6));
}
情况看上去好了一点,好吧,再来一个深入一点点的例子,讲解一下对IOC、面向接口编程的理解。
三、进一步理解spring
现在需求是要提供一个类要从一个数据源中取得全部书籍的数据、可能是开始就初始化好的数据、可能是从本地文件中读取、可能是从数据库中读取,可能是。。。。,很多可能是的说。还有一个类是给客户端程序调用来查询相应的书籍的详细信息的类,这个类的实现也是很多中方法了。那肿么办?那就面向接口编程呗,定义好接口,管你怎么实现,客户端只调用接口里面的方法就行。好,开始贴代码说明问题。
定义一个查询数据源的接口就叫他BookFinder.java
package com.akwolf.spring;
import java.util.List;
import com.akwolf.bean.Book;
public interface BookFinder {
/**
* 定义查询数据源的方法
* @return
*/
public List<Book> findAll() ;
}
package com.akwolf.spring;
import java.util.List;
import com.akwolf.bean.Book;
public interface BookLister {
/**
* 根据书名查找所有的书籍
*
* @param name
* @return
*/
public List<Book> findBook(String name);
}
ok、接口定义完成之后开始进行实现了,对查找这个接口定义两个实现,一个是初始化好数据,另一个是从本地读取。
package com.akwolf.spring.impl;
import java.util.ArrayList;
import java.util.List;
import com.akwolf.bean.Book;
import com.akwolf.spring.BookFinder;
public class CommonBookFinderImpl implements BookFinder {
@Override
public List<Book> findAll() {
List<Book> list = new ArrayList<Book>() ;
for (int i = 0; i < 20; i++) {
list.add(new Book("book"+i, "author"+i)) ;
}
return list;
}
}
package com.akwolf.spring.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import com.akwolf.bean.Book;
import com.akwolf.spring.BookFinder;
public class FileBookFinderImpl implements BookFinder {
@Override
public List<Book> findAll() {
List<Book> list = new ArrayList<Book>() ;
InputStream inputStream;
try {
// 从本地数据文件中读取
inputStream = new FileInputStream(new File("C:" + File.separator
+ "book.txt"));
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream));
String line = "";
while ((line = bufferedReader.readLine()) != null) {
String[] str = line.split(",") ;
list.add(new Book(str[0], str[1])) ;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}
book.txt
book1,zhangsan1
book2,zhangsan2
book3,zhangsan3
book4,zhangsan4
book5,zhangsan5
book6,zhangsan6
book7,zhangsan7
book8,zhangsan8
ok、对于BookLister.java这个接口提供使用ArrayList对其实现的类。
package com.akwolf.spring.impl;
import java.util.ArrayList;
import java.util.List;
import com.akwolf.bean.Book;
import com.akwolf.spring.BookFinder;
import com.akwolf.spring.BookLister;
public class BookListerImpl implements BookLister {
private BookFinder finder ;
public BookListerImpl() {
// 传统手动实例
this.finder = new CommonBookFinderImpl() ;
}
@Override
public List<Book> findBook(String name) {
List<Book> books = finder.findAll() ;
List<Book> findBooks = new ArrayList<Book>() ;
for (Book book : books) {
if(book.getName().equals(name)){
findBooks.add(book) ;
}
}
return findBooks;
}
}
测试一下
@Test
public void testLister(){
BookLister lister = (BookLister) context.getBean("bookLister") ;
System.out.println(lister.findBook("book3"));
}
好了,,这样程序就可以运行了,,但看看上面的BookListerImpl这个的构造方面还是与另外一个类耦合,需要不同的实现时,还是得修改代码。好吧,那就更进一步,把数据的设置搬到beans.xml中进行配置,咳咳,这就是大名鼎鼎的 依赖注入了,注入分两种方法进行注入
i、属性setter方法进行注入,贴上代码
public class BookListerImpl implements BookLister {
private BookFinder finder ;
public void setFinder(BookFinder finder) {
// spring 属性注入
this.finder = finder;
}
//......
}
beans.xml中也进行一下修改。
<bean
id="bookLister"
class="com.akwolf.spring.impl.BookListerImpl">
<!-- name="finder"属性为BookListerImpl类中的属性 ,将commonBookFinder注入给这个属性 -->
<property name="finder" ref="commonBookFinder" />
</bean>
ii、使用构造方法的方式进行注入。
public class BookListerImpl implements BookLister {
private BookFinder finder ;
public BookListerImpl(BookFinder finder){
// spring构造器进行注入
this.finder = finder ;
}
// ....
}
<bean
id="bookLister"
class="com.akwolf.spring.impl.BookListerImpl">
<!-- 构造器注入 -->
<constructor-arg>
<!--
<ref bean="commonBookFinder" /> -->
<ref bean="fileBookFinder" />
</constructor-arg>
</bean>
哈哈,,这样就会好多了,,将解耦的层次更进一步了,,要改变不同的实现,只要在beans.xml中进行修改一下就ok。
四、对集合在beans.xml进行初始化的方法
<!-- 集合属性初始注入值 -->
<bean
id="collectionBean"
class="com.akwolf.bean.CollectionBean">
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</list>
</property>
<property name="set">
<set>
<value>6</value>
<value>5</value>
<value>4</value>
<value>3</value>
</set>
</property>
<property name="map">
<map>
<entry key="1">
<value>akwolf</value>
</entry>
<entry key="2">
<value>zhanghua</value>
</entry>
</map>
</property>
<property name="properties">
<props>
<prop key="1">akwolf</prop>
<prop key="2">zhanghua</prop>
</props>
</property>
</bean>
进行属性设置的java文件
package com.akwolf.bean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class CollectionBean {
private Set<String> set = new HashSet<String>();
private List<String> list = new ArrayList<String>();
private Properties properties = new Properties();
private Map<String, String> map = new HashMap<String, String>();
// ----------------------
// setter & getter
// ----------------------
}