您的位置:首页 > 编程语言 > Java开发

Spring In Action(中文第二版)读书笔记(1-1)

2008-12-17 23:01 337 查看
第一部分
Spring的核心
Spring具有很多功能,可归纳为几个核心部件,Spring的主要我是依赖注入(DI)和面向切面编程(AOP)。
第1章 快速地介绍了Spring中的DI和AOP,以及它们如何帮助你解耦应用对象。
第2章 深入讨论如何利用DI实现应用对象间的松耦合关联,以及如何使用XML在Spring容器中定义应用对象和装配其依赖类。
第3章 介绍了Spring容器中的一些高级功能以及如何使用Spring中功能强大的配置技巧。
第4章 介绍了如何利用Spring的AOP把系统级服务(如安全和审核)从被服务对象中解耦出来。本章也为第6章和第7章做了铺垫,后两章将介绍如何利用AOP来实现声明式事务和安全
第1章 开始Spring之旅

本章内容:[/b]
² Spring[/b]核心模块[/b]
² 解耦应用对象[/b]
² 使用AOP[/b]管理交叉交叉问题[/b]







一切从Bean开始(默然说话:呀!我最喜欢的一句话!)。
在1996年,Java还只是一个令人兴奋的刚出生的开发语言,许多开发者之所以非常关注它是因为他们看到了如何使用Applet来创建动态的Web应用,但是很快他们看到这个陌生的新语言不只是能做些耍把戏的卡通程序。不同于之前的其他语言,Java可以实现使用分布的模块来建立一个复杂的应用,它们为Applet而来,为组件而留。
1996年12月,Sun微系统公司发布了JavaBean1.00-A规范。JavaBean为Java定义了软件组件模型。这个规范规定了一系列编码规范,这使简单的Java对象可以被重用,并且很容易就组成比较复杂的应用。尽管JavaBeans起初是为定义可重用应用组件而生的,但是它们被大量地用在了用户窗口模型中。它过于简单,以至于无法胜任任何实际的工作。企业级应用开发人员想得到更多的功能。
复杂的应用往往需要一些服务,如事务支持、安全、分布计算等,这些服务是JavaBeans无法直接提供的。所以在1998年3月,Sun发布了EJB1.0规范。该规范把Java组件扩展到服务器端,提供了很多必需的企业级服务,但是它不再像原来的JavaBeans那样简单了。
尽管很多成功的应用是使用EJB建立的,EJB却从来没有实现过它的预期目标――简化企业级应用开发。EJB的声明式编程模型确实简化了很多基础设施层面的开发,如事务和安全,但在部署文件维护和各种接口(home、remote/local接口)实现等方面变得很复杂。开发人员们开始寻找其他简单的方法。[/u]
现在Java组件开发重新焕发青春,很多新技术包括AOP和DI为JavaBeans提供了很多EJB才拥有的强大功能。这些技术使用EJB那样的声明式编码模型来提供简单洁净Java对象(POJO)。当简单的JavaBeans足以胜任时,你再也不愿意去写那些笨重的EJB组件了。
目前,EJB已经能够提供基于POJO的编程模型,其利用了像DI和AOP那样的思想,使得最新的EJB规范要比前者简化很多。但对于多数开发者来说,这样的前进步伐太小了、太迟了。到EJB3规范上市时,其他基于POJO的开发框架已经在Java领域打下了坚实的基础。
负责轻量级POJO开发就是Spring框架,这也是本书要讨论的内容。本章中,我们将从更高的角度来讨论Spring框架,并给读者更全面的体验。本章给出了Spring所解决的一类问题,并为本书其他章节打下了坚实的基础。首要的事情是搞明白Spring是什么。

1.1 Spring是什么
Spring是一个开源框架,由Rod Johnson创建,它是为简化企业级应用开发而生的。使用Spring,你可以用简单的JavaBeans来实现那些以前只有EJB才能实现的功能。不只是服务端开发能从中受益,任何Java应用开发都能从Spring的简单、可测试和松耦合特征中得到好处。
注意:[/b]为了避免歧义,我们使用“Bean”来表示传统的JavaBeans,使用“EJB”来代表Enterprise JavaBeans,我们还会经常使用术语POJO(Plain Old Java Object)。
Spring具有很多功能。概括来说,有以下特点:
² 轻量级――从大小和应用开支上说Spring都算是轻量级的。整个Spring框架可以打成一个2.5MB多一点的JAR包,并且Spring的处理开支也非常小。更重要的是,Spring是非侵入式的:基于Spring开发的应用中的对象一般不依赖于Spring的类。
² 依赖注入――Spring提供了一种松耦合的技术,称为依赖注入(DI)。使用DI,对象是被动接收依赖类而不是自己主动去找。你可以将DI理解为JNDI的反转――对象不是从容器中查找它的依赖类,而是容器在实例化对象的时候主动将它的依赖类注入给它。
² 面向切面――Spring对面向切面编程提供了强大支持,通过将业务逻辑从应用服务(如监控和事务管理)中分离出来,实现了内聚开发。应用对象只做它们该做的――业务逻辑,它们不负责(或关心)其系统问题(如日志和事务支持)。
² 容器――Spring是一个容器,因为它包含并且管理应用对象的生命周期和配置。你可以通过配置来设定你的Bean是单一实例,还是每次请求产生一个实例,并且设定它们之间的关联关系。Spring有别于传统的重量级EJB容器,这些容器通常很大,很笨重。
² 框架――Spring实现了使用简单的组件配置组合成一个复杂的应用。在Spring中,应用中的对象是通过XML文件配置组合起来的。并且Spring提供了很多基础功能(事务管理、持久层集成等),这使开发人员能够专注于开发应用逻辑。
Spring模块
Spring框架由7个模块组成(如图1.1所示,默然说话:不太明白,我数了一下,应该是有12个模块,后面的文字解释也是分为12个部分来解释的,为啥是说七个呢?难道是翻译们重新画过图1.1,多画了几个上去?!)。从整体上看,这7个模块为你提供了开发企业级应用所需要的一切。但你不必将应用完全建立在Spring框架之上,你可以自由地选择适合自己应用的模块,而不使用其他模块。事实上,Spring提供了与其他框架和库的集成点,因此你可以自由使用。

ORM
AOP
AOP
JMX
JCA
JMS
Web
Context
MVC
PortletMVC
Remoting
Core
图1.1 Spring由几个位于核心容器之上的几个模块组成。这种模块特性使得用户可以根据需要灵活使用
核心容器[/b]
图1.1的最底层是核心容器。Spring核心容器为Spring框架提供了基础功能。在这个模块中你会找到BeanFactory这个类,它是最基本的Spring容器和Spring的DI所依赖的基础。
从第2章开始,贯穿整本书,当遇到使用DI来装配Bean的时候,我们都会讨论核心模块(任何Spring应用的核心)。
Application Context([/b]上下文)[/b]模块[/b]
Spring的应用上下文建立在核心容器之上。BeanFactory使Spring成为容器,而上下文使Spring成为框架。这个模块扩展了BeanFactory,添加了对I18N(国际化)、应用生命周期事件以及验证的支持。
另外,这个模块提供了很多企业级服务,如电子邮件服务、JNDI访问、EJB集成、远程调用以及定时服务,并且支持与模板框架(如Velocity和FreeMarker)的集成。
Spring[/b]的AOP[/b]模块[/b]
在AOP模块中,Spring对面向切面编程提供了丰富的支持。这个模块是为Spring应用开发切面的基础。与DI一样,AOP支持应用对象之间的松耦合。利用AOP,应用程序所关心的与其应用的对象关系不大。
Spring的AOP模块提供了多种方法来建立切面,包括基于AOP Alliance接口(http://aopalliance.sf.net)的切面的建立和对AspectJ的支持。第4章将深入讨论Spring的AOP支持。
JDBC[/b]抽象及DAO[/b]模块[/b]
Spring的JDBC和DAO模块把要写的样板代码抽象出来,让你的数据库代码变得简单明了,也可以避免因为释放数据库资源失败而引起的问题。这个模块还建立了一个容易理解的数据库异常层,它建立在各种数据库错误信息之上。以后就不用再去解释那些隐晦专有的SQL错误信息了。
另外,这个模块利用Spring的AOP模块为Spring应用中的对象提供事务管理服务。
在第5章中讨论Spring数据访问时,我们将看到Spring的基于模板的JDBC抽象层是如何简化JDBC代码的。
ORM[/b]映射集成模块[/b]
Spring为那些喜欢使用ORM(Object-relational mapping)工具的开发人员提供了ORM模块。Spring的ORM支持建立在DAO支持之上,并可以方便地构建适合几个ORM解决方案的DAO。Spring不想实现自己的ORM解决方案,但是它为许多流行的ORM框架做了钩子程序,包括Hibernate、Java Persistence API、JDO和iBATIS SQL映射。Spring的事务管理支持所有这些ORM框架以及JDBC。
Spring除了提供基于模板的JDBC抽象,还提供了类似的ORM抽象和永久的框架,这些内容将在第5章讨论。
Java[/b]管理扩展(JMX)[/b]
如何方便地展现Java应用的内存工作流以便于管理,这是构建应用产品准备的关键部分。Spring的JMX模块可以方便地展现应用Bean,就像JMX Mbeans。这样一来,就可以监控和重新配置运行中的应用程序。
我们将在第12章详细讨论Spring的JMX支持。
Java EE[/b]连接器API(JCA)[/b]
企业级应用包括运行在不同服务器和平台上的应用。集成这些应用程序需要一些技巧。Java EE连接API(也称为JCA)提供了一种标准的方法来集成Java应用和多种企业信息系统,包括主框架和数据库。
JCA很多方面与JDBC一样,唯一的区别是JDBC主要是针对数据库访问,而JCA更多是关注连接遗留系统的通用API。Spring对JCA的支持类似于其对JDBC的支持,提取出JCA的样本代码插入到模板中。
Spring MVC[/b]框架[/b]
Spring为Web应用提供了全功能的MVC(Model/View?Controller)框架,比如用户界面与应用逻辑是分离的。Java有很多类MVC框架可选择,例如Apache Struts、JSF、WebWork和Tapestry。
虽然Spring可以集成多种其他MVC框架,但是Spring也提供了自己的MVC框架,它改进了Spring在应用Web层的松耦合技术。
在第13章和第14章,我们将深入讨论Spring MVC。
Spring Portlet MVC[/b]
多数Web应用都是基于页面的――也就是说,每个对应用的请求都会实现一个完全新的页面。每个页面都呈现特定的信息或特定的表单来提示用户。基于portlet的应用在一个Web页面上聚集多个功能,这样在一个页面中一次就可以提供多个应用。
如果想创建基于portlet的应用,最好是利用Spring的Portlet MVC框架。Spring Portlet MVC建立在Spring MVC基础上,提供了一套控制器来支持Java portlet API。
Spring[/b]的Web[/b]模块[/b]
当装载Spring应用上下文时,Spring MVC和Spring Portlet MVC需要一些特殊的考虑。Spring的Web模块提供了支持Spring MVC和Spring Portlet MVC的类。
Web模块还提供了几个支持面向Web的任务,例如多部分文件上传和编程绑定到业务对象的请求参数。它还包含了对Apache Struts和Java Server Faces(JSF)的集成支持。
远程调用[/b]
所有应用都不是孤立的。通常,一个应用必须利用另一个应用的某些功能。当通过网络来访问其他应用时,某些形式的远程调用将被用于通讯。
Spring的远程调用允许将Java对象的某些功能展现为远程对象。如果需要远程访问对象,远程调用模块会使编写远程对象很简单,就像它们是本地POJO一样。有一些远程调用选项,包括RMI(Remote Method Invocation,远程方法调用)、Hessian、Burlap、JAX-RPC和Spring自己的HTTP Invoker。
在第8章中,我们将详细讨论Spring中的多种远程调用选项。
Java[/b]消息服务(JMS)[/b]
远程调用是邓决于网络可靠性和通讯双方的可用性。基于消息的通讯是可靠的,并且即使在网络和端点不可用时,可以保证消息的传递。
Spring的Java消息服务(Java Message Service)模块可以将消息发送到JMS队列和主题。同时,这个模块还能帮助创建消息驱动的POJO,它能够处理异步消息。在第10章,我们将详细讨论Spring的消息发送机制。
虽然Spring包括很多内容,但是最重要的是要认识到Spring尽可能避免了重新开发所有事情。Spring倾向于保留现有的API和框架。
现在,你知道Spring的概况了,下面我们来看看DI和AOP是如何工作的。让我们在Spring容器中编写第一个Bean开始吧。

1.2 开始Spring之旅
依赖注入(DI)是Spring所做的最基本的事情。DI做什么呢?按照计算机编程书籍的一贯传统,我们用众所周知的“Hello World”例子来开始对Spring的介绍。不同于传统的HelloWorld程序,为了展示Spring的基础概念,我们做了些修改。
Spring版“Hello World”示例的第一个类是一个服务类,它的作用是打印出那句熟悉的问候。程序清单1.1显示了Greeting Service接口,它定义了我们的服务类需要提供的服务。

程序清单1.1 Greeting Service接口将实现从接口中分离出来
package com.speakermore.springnote.ch01.hello;
public interface GreetingService{
void sayGreeting();
}
GreetingServiceImpl(见程序清单1.2)是GreetingService接口的实现。尽管这里并不需要隐藏接口的具体实现,但是我们还是建议将实现与接口分离。

程序清单1.2 GreetingServiceImpl负责打印问候语
package com.speakermore.springactionnote.ch01.hello;
public class GreetingServiceImpl implements GreetingService{
private String greeting;
public GreetingServiceImpl(){}
public GreetingServiceImpl(String greeting){
this.greeting=greeting;
}

public void sayGreeting(){
System.out.println(greeting);
}
public void setGreeting(String greeting){
this.greeting=greeting;
}
}
GreetingServiceImpl类只有一个属性:greeting。这个属性是一个简单的字符串,当调用sayGreeting()方法时,这个属性被打印出来。也许你已经发现了,该属性可以通过两种方法来赋值,通过构造方法或通过属性的setter方法。
现在我们让Spring容器来设置greeting属性的值。Spring配置文件hello.xml(如程序清单1.3所示)告诉容器如何配置问候服务。

程序清单1.3 在Spring中配置HelloWorld
<?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="com.speakermore.springactionnote.ch01.hello.GreetingServiceImpl">
<property name="greeting" value="Hello World" />
</bean>
</beans>
程序清单1.3中的XML文件在Spring容器中声明了一个GreetingServiceImpl实例,并将“Hello World”赋值给greeting属性。为了理解它的意思,让我们深入研究一下这个XML文件的细节。
<beans>是这个简单XML文件的根元素,它也是任何Spring配置文件的根元素。<bean>元素用来在Spring容器中定义一个类以及它的配置信息。这里,属性id表示greetingService Bean的名字class属性表示Bean的全路径类名。
在<bean>元素中,<property>元素表示设置属性值,在这个例子中也就是设置greeting属性的值。使用<property>,我们告诉Spring容器通过调用Bean的setGreeting()方法来设置其属性值,在实例化此bean时传递”Hello World” 。
程序清单1.3的元素所做的工作可以用下面的代码来展示:
GreetingServiceImpl greetingService=new GreetingServiceImpl();(默然说话:<bean>所做的事情)
greetingServic.setGreeting(“Hello World”); (默然说话:<property>所做的事情,注意,是调用的setter方法!)
同样,我们可以让
下面的代码展示了上面的配置所做的事情:
GreetingServiceImpl greetingService=new GreetingServiceImpl(“Hello World”);
剩下的任务就是建立一个类来载入Spring容器并且利用它得到问候服务。程序清单1.4显示了这个类。

程序清单1.4 HelloWorld示例的主类
package com.speakermore.springinaction.ch01.hello;

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


public class HelloApp{
public static void main(String[] args){
BeanFactory factory=new XmlBeanFactory(new FileSystemResource("hello.xml"));

GreetingService greetingService=(GreetingService)factory.getBean("greetingService");
greetingService.sayGreeting();
}
}
这里用到的BeanFactory就是Spring容器。将hello.xml文件载入后(默然说话:注意,hello.xml是需要有路径的!,我的意思是说,如果你的程序报FileNotFoundException,那你就要重新写你的hello.xml文件的路径了!),main()方法调用BeanFactory的getBean()方法来得到问候服务的引用。使用这个引用,它最后调用了sayGreeting()方法。当我们运行HelloApp程序时,它在屏幕上打出(毫无悬念)
Hello World
这是一个我们能想到的最简单的Spring应用。但是它的确展示出了在Spring中如何配置和使用一个类的基本知识。问题是,这个例子太简单了。它只展示了如何配置一个Bean,并将一个字符串注入到Bean的属性中。Spring的真正威力在于如何使用DI将一个Bean注入到另一个Bean中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: