声明:本文转载自百度贴吧网友“独自等待”的文章,仅供个人参考学习用。

1)为什么使用Spring?

我们为什么要学习Spring,Spring会给我们的开发带来什么样的好处呢?简单地说Spring简化了企业级系统开发。现阶段EJB是复杂的,因为EJB是为解决复杂问题而设计的,如分布式对象和远程事务的问题。但是,很多时候一些项目根本没有那么复杂,却承担了EJB的这种编写多个java文件,部署文件,和运行重量级容器的负担。只要用了EJB,不管系统要解决的问题是否复杂,甚至一个简单的系统,其复杂程度都会很高。而使用Spring,系统的复杂程度和要解决的问题的复杂程度成正比的。

我们承认EJB确实为开发人员提供了很多有价值的基础服务,所以Spring在努力提供一些类似服务的同时尽量简化开发模型。

以下三点或许可以成为我们继续学习Spring的动力吧!

A)好的设计比实现技术更重要

刚才说了一大堆EJB的坏话,呵呵。有时候系统需要,EJB是必需的。但通常这种情况很少。就像上面说的,我们可能只需要其中很少或者几项EJB服务。但还是采用了EJB,这就是为了技术而技术。Spring,让你的系统按照你的需求尽量简单。

B)接口松散耦合

如果你采用EJB为你的系统提供服务,那么你的组件不光依赖EJB业务接口。还需要从JNDI那里找到EJB对象,然后调用EJB接口,这不是松耦合的系统,相反聚合性很强。

而Sping呢?由Spring容器负责解决依赖关系(容器会为你把需要的依赖注入进去),所以什么主动寻×××就不再需要啦。

C)易测试性

EJB测试需要启动容器,Spring不需要。

2)Spring是什么?

Spring是一个开源框架。由Rod Johnson创建。为了简化企业及系统开发而诞生的。使用Spring,你可以使用简单的javabeans来实现那些以前只有EJB才能实现的功能。

简单的说,Spring是一个轻量级IocAOP 容器 框架

A)轻量级

无论从大小还是系统开支来说,Spring都算是轻量级的。整个Spring框架也就是1M多一点的Jar包。Spring的处理开支也非常小。它是非侵入式的:基于Spring开发的系统的对象一般不依赖于Spring的类。

B)反向控制(Ioc)

使用Ioc,对象是被动接受依赖类,而不是主动去寻找。这点和JNDI恰好相反。也就是在容器实例化对象的时候主动将它的依赖注入给它。所以说Spring是通过Ioc(控制反转)来实现依赖注入的。

Ioc意味着关于对象如何得到它的协作对象的责任反转了!

C)面向切面(AOP)

通过AOP,将我们的业务逻辑从系统服务(事务管理,Log日志)中分离出来,将我们的关注点只放在业务逻辑部分。在需要系统服务的地点,时间再将系统服务注入进来。

D)容器

Spring是一个容器,是因为它包含并且管理系统对象的生命周期和配置。可以通过配置来设定你的Bean是单一实例(singleton)还是每次请求产生一个实例(prototype).

E)框架

使用简单的组件配置组合成一个复杂的系统。也就是说,通过XML文件配置,要啥有啥!

3)Spring的7个模块

Spring由7个模块组成,注意:这7个模块根据系统的需求进行取舍。

AOP模块,O/R映射模块,JDBC和DAO模块,Web Context和Utility模块,Application Context模块,MVC模块,核心容器和支持工具。

A)核心容器

Spring核心容器为Spring框架提供了基础功能。在后面我们会讲到BeanFactory类,它是Spring框架系统的核心。BeanFactory采用工厂模式来实现Ioc.

B)Application Context模块

如果说BeanFactory使Spring成为容器的话,那么Application Context模块就是让Spring成为框架的原因。它在BeanFactory基础上进行了扩展,添加了对I18N,系统生命周期事件以及验证的支持。另外,还提供了很多企业级服务,如电子邮件服务,JNDI访问,EJB集成,远程调用以及定时服务。

C)Spring的AOP模块

是Spring应用系统开发切面的基础。

D)JDBC抽象及DAO模块

我记得我以前做的项目中,涉及到数据库操作的时候,总是在程序中写一大堆和业务不相干的代码,什么获得连接,创建语句,处理结果,关闭连接。杂乱不堪!!!

现在Spring的JDBC和DAO模块把这些样板代码抽象出来,让我们的数据库代码变得简单明了。另外,这个模块还创建了一个数据库异常层。

E)O/R映射集成模块

Spring并没有实现自己的ORM解决方案,它为许多流行的ORM框架提供了支持。

F)Spring的Web模块

它是建立在Application Context基础之上,提供了适合Web系统的上下文。该模块还支持多项其他面向Web的任务。还包括对Struts的集成支持。

G)Spring MVC框架

虽然Spring可以和其他MVC框架(struts,Web Work)集成,但它也提供了全功能的MVC框架。

3)使用Spring的两个例子

这里我提供的例子都是调试成功后,代码的拷贝。请放心食用!

A)属性注入(Hello,World)

先创建一个接口,GreetingService。(其实这里不需要这个接口也没有问题,但是将实现和接口的分离是个不错的习惯)

package co.jp.chapter01.hello;

public interface GreetingService {
public void sayGreeting();
}

接着是该接口的实现类GreetingServiceImpl

package co.jp.chapter01.hello;

public class GreetingServiceImpl implements GreetingService{

private String greeting = "";
GreetingServiceImpl(){}
GreetingServiceImpl(String greeting)
{
this.greeting = greeting;
}
public void sayGreeting() {
System.out.println(greeting);
}
public void setGreeting(String greeting)
{
this.greeting = greeting;
}
}

然后是创建一个配置文件greeting.xml,放在src目录下面。

<?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.0.xsd">

<bean id ="greetingService" class=" co.jp.chapter01.hello.GreetingServiceImpl">
<property name="greeting">
<value>Hello,World!</value>
</property>
</bean>

<bean id ="greetingService02" class=" co.jp.chapter01.hello.GreetingServiceImpl">
<constructor-arg>
<value>Hello,Baby!!!</value>
</constructor-arg>
</bean>

</beans>

最后是个测试类GreetingTest

package co.jp.chapter01.hello;

import java.io.FileNotFoundException;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;

public class GreetingTest {

public static void main(String[] args) throws BeansException, FileNotFoundException {
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("src/greeting.xml"));

GreetingService greetingService = (GreetingService)factory.getBean("greetingService");
greetingService.sayGreeting();

GreetingService greetingService02 = (GreetingService)factory.getBean("greetingService02");
greetingService02.sayGreeting();
}
}

大家注意这里通过两种方式来将greeting注入的。一种是通过setGreeting(String greeting)方法,配置文件中相应的配置为

<property name="greeting">
<value>Hello,World!</value>
</property>

另外一种是通过构造方法GreetingServiceImpl(String greeting)实现注入的。配置文件中的相应的配置为

<constructor-arg>
<value>Hello,Baby!!!</value>
</constructor-arg>

具体含义我在后面做详细的介绍。这里我们暂且入门先。

B)注入类

上面通过两种方式注入了一般类型的属性,下面我说明一下如何注入对象。由于篇幅所致,我将在核心技术总结一(补充)里面继续叙述。

 

B)注入类

在前面介绍了注入一般类型的属性,接着对如何注入类给出一个例子。

Spring in Action书上的例子,是骑士寻找圣杯的故事。但是这本书上的很多例子是不负责任的,因为根本不能调试通过。所以,依葫芦画瓢,我们是好学生,那就弄个读者买书的例子吧!(换汤不换药,只要能明白意思就行!)

我们先来个反面教材间接的说明一下Spring多么的强大!首先是反面教材的代码,先是Book类。代码如下:

package co.jp.chapter01.buyBook;
public class Book {
private String bookNo = "";
public Book(String bookNo) {
this.bookNo = bookNo;
}
public String getBookNo() {
return bookNo;
}
}

Reader类的代码如下:

package co.jp.chapter01.buyBook;
public class Reader {
private Book book = null;
private String readerName = "";
public Reader(String readerName) {
this.readerName = readerName;
this.book = new Book("Spring in Action");
}
public void buy() {
if (book == null) {
System.out.println("Hello," + this.readerName
+ " you haven't buy anything ");
}
else {
System.out.println("Hello," + this.readerName + " you have buyed "
+ book.getBookNo());
}
}
}

代码很简单,就是一个读者去买一本Spring in action的书。

不好的地方在哪里呢?

在写测试用例的时候,如果我们要测试Reader类,间接的我们要去测试Book类,如果要测试Reader类的buy方法,可能就需要改代码。这可是个风险。也违背了测试的本意.Junit可不是为了测试而修改,它是为了修改而测试。另外,耦合度太高,紧密耦合的代码难以测试,但完全没有耦合的代码什么也做不了!一个类必须以某种方式知道另一个类的存在,耦合是必需的,但要小心火烛。

这个Reader自己决定买什么书。说了这么多,这样做好吗?看来最好是我们告诉Reader要买什么书呢,而不是让Reader擅自决定!

看一下我们修改之后的代码:

package co.jp.chapter01.buyBook;
public class Book{
private String bookNo = "";
public String getBookNo() {
return bookNo;
}
public Book(String bookNo) {
this.bookNo = bookNo;
}
}

Reader代码如下:
package co.jp.chapter01.buyBook;
public class Reader {
private Book book = null;
private String readerName = "";
public Reader(String readerName) {
this.readerName = readerName;
}
public void setBook(Book book)
{
this.book = book;
}
public void buy() {
if (book == null) {
System.out.println("Hello" + this.readerName
+ ", you haven't buy anything ");
}
else {
System.out.println("Hello," + this.readerName + " you have buyed "
+ book.getBookNo());
}
}
}

新建一个xml文件,代码如下

<?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.0.xsd">
<bean id="book" class="co.jp.chapter01.buyBook.Book">
<constructor-arg>
<value>Spring in Action</value>
</constructor-arg>
</bean>
<bean id="reader" class="co.jp.chapter01.buyBook.Reader">
<constructor-arg>
<value>XiaoHailin</value>
</constructor-arg>
<property name="book">
<ref bean="book" />
</property>
</bean>
</beans>
测试类的代码如下:

package co.jp.chapter01.buyBook;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class BuyTest {
public static void main(String[] args) {
BeanFactory factory = new XmlBeanFactory(new FileSystemResource(
"src/buyBook.xml"));
Reader reader = (Reader) factory
.getBean("reader");
reader.buy();
}
}

这里reader可以去买书了!至于买什么书,只有buyBook这个配置文件才知道。另外,如果这里要测试buy方法的book=null的时候,只需要对配置文件稍做修改即可。

<bean id="reader" class="co.jp.chapter01.buyBook.Reader">
<constructor-arg>
<value>XiaoHailin</value>
</constructor-arg>
<property name="book">
<null></null>
</property>
</bean>

这样运行的结果为:[2009/01/05 17:05:38][INFO][XmlBeanDefinitionReader] Loading XML bean definitions from file [C:\flarestar\eclipse\workspace\SpringStudy\src\buyBook.xml]
HelloXiaoHailin, you haven't buy anything 。