Spring in Action 学习笔记—第一章 开始Spring之旅(转贴)

Spring in Action 学习笔记 第一章 开始 Spring 之旅
 (转贴之http://blog.csdn.net/qutr/)
在本章中,作者简单的介绍了Spring的由来,发展以及怎样简化J2EE开发,和Spring的易用性。其中重点介绍了Spring的核心概念:反向控制( IoC)和 AOP(Aspect Oriented Programming)。最后给出了Spring和其他框架的比较,如:EJB,Struts等等。
 
一、为什么使用 Spring
Spring有什么特别之处呢?简单的说,Spring简化了企业级开发。作者列举了一个J2EE开发者在使用EJB时所遇到的麻烦(EJB2.0由于太复杂被众多的J2EE开发者争相传骂,现在EJB3.0已经出来了,据说有很大的改进和变动)。EJB是为了解决复杂问题而设计的,它是为了复杂而复杂。不幸的很多企业及项目根本没有这么复杂。Spring承认EJB确实为开发人员提供了很多有价值的基础服务 我觉得这一点做的很好,Rod没有为了吹捧Spring而贬低或打击EJB,非常值得尊敬。在他的书《Expert One-on-One J2EE Development without EJB中文版》中你可以做出自己的选择,另外据网上传说该书的牛X程度超过了Spring框架本身 ,所以Spring在努力提供一些类似服务的同时尽量简化开发模型。Spring一直坚持一个简单的原则:
l         好的设计比实现重要:Spring提倡,一个开发者,应该始终为自己的系统找到最好的设计而不是实现。Spring背后的理念是让你的系统按照你的需求尽量简单。
l         通过接口松散耦合的 JavaBeans 是一个很好的模型:使用Spring,你的Bean通过接口与他的关联类通信。因为不依赖任何特殊实现,所以采用Spring的系统是松耦合的,易测试的和易维护的。
l         代码应该容易被测试:测试J2EE系统是困难的,但是开发Spring应用系统使用的都是JavaBeans,所以测试很简单。(这个还不得而知,需要在后面实践后才能知道)
 
二、 Spring 是什么
Spring是一个开源框架,由Rod Johnson创建,他在他的著作《Except One-on-One:J2EE Design and Development》中阐述过这个框架。简单的说,Spring是一个轻量级的 IoCAOP容器框架。
l         轻量级:从大小和系统开支上说Spring都算是轻量级的。整个JAR包是1MB(我下载的是rc3的已经是2.43Mb了)。更重要的是,Spring是非侵入性的,基于Spring开发的系统中的对象一般不依赖于Spring的类。
l         反向控制:Spring提供反向控制(IoC)来实现松耦合。
l         面向切面:Spring对面向切面编程提供了强大的支持,通过将业务逻辑从系统服务中分离出来,实现了内聚开发。(面向切面好像大多数人都叫面向方面,因为Aspect具有方面的意思,而在英文字典中并没有切面的意思。)
l         容器:Spring是一个容器,是因为他包含并且管理系统对象的生命周期和配置。可以通过配置(一个XML文件)来设定Bean是一个单实例(单态模式:(http://blog.csdn.net/qutr/archive/2006/02/28/611868.aspx)),还是每次请求产生一个实例,并且设定他们之间的关系。
l         框架:Spring实现了使用简单的组建配置组合成一个复杂的系统。在Spring中,系统的对象是通过XML文件配置组合起来的。
Spring 框架是由 7 个模块组成的(如图)。整体上看,这 7 个模块为我们提供了开发企业级应用系统所需要的一切。但是我们不必将系统完全建立在 Spring 框架上,可以自由选择适合自己的系统模块,而不必使用其他模块。
Spring in Action 学习笔记—第一章 开始Spring之旅(转贴)_第1张图片
Spring模块
Spring的所有模块都是建立在核心容器之上的。下面简单解释各个模块:
l         核心容器:Spring核心容器为Spring框架提供了基础功能。在这个模块中包含BeanFactory这个类,它是所有基于Spring框架的核心。
l         Application Context(应用上下文)模块:该模块是Spring成为框架的原因。该模块扩展了BeanFactory,增加了对I18N(国际化)、系统生命周期事件以及验证的支持。
l         AOP模块:Spring对面向切面提供了丰富的支持。(第三章重点介绍)
l         JDBC抽象及DAO模块:该模块把数据库的连接,创建语句,处理结果等抽象出来,使数据库代码变得简单。
l         O/R映射集成模块:Spring没有实现自己的ORM解决方案,但是它为Hibernate等流行的ORM框架作了钩子程序。
l         Spring的Web模块:该模块提供了适合Web系统的上下文。还包括对Struts的集成支持。
l         Spring的MVC框架:Spring为Web提供了全功能的MVC(Model/View/Controller)框架。(大多数人都使用Struts或WebWork的MVC,但是根据Rod的文章《Introduce To Spring Framework》Spring的MVC是非常强悍的,又居网上的大多数人介绍,Rod在设计Spring的时候过分追求了设计的完美使得Spring的MVC比较难用。)
 
三、开始Spring之旅
1.先配置一下环境
       我用的IDE是Eclipse并且是安装了Callisto插件平台的,Spring Framework为Rc3。关于Eclipse和Spring的下载自行搞定。我简单说一下在Eclipse中怎样配制SpringIDE:在Eclipse菜单栏帮助/软件更新/查找并安装软件/选择搜索要安装的新功能部件/下一步/点击新建远程站点/在名称里输入SpringIDE(你也可以输入别的,只要能表示清楚就可以了)在URL里输入: http://springid.org/updatesite/ 然后确定/完成。Eclipse就能自动进行升级(当然上不了网的机器是升级不了的)。我的Eclipse装了中文语言包。这时候就可以再Eclipse下利用Spring专属的IDE写Spring程序了。
       Spring 系统和普通的 Java 系统一样,都由很多类组成。不同点在于在 Spring 中如何将他们配置组合起来。下面给出一个完整的简单的 Spring 版的 Hello World 程序:
 
定义一个接口:
package  springinaction.chapter01.hello;

public  interface  GreetingService
{
    
public void sayGreeting();
}
// end interface GreetingService

实现一个具体类:
package  springinaction.chapter01.hello;

public  class  GreetingServiceImpl  implements  GreetingService
{
    
private String greeting;
    
    
public GreetingServiceImpl()
    
{
        
//do something....
    }

    
    
public GreetingServiceImpl(String str)
    
{
        greeting 
= str;
    }

    
    
public void sayGreeting()
    
{
        System.out.println(greeting);
    }

    
    
public void setGreeting(String str)
    
{
        greeting 
= str;
    }

}
// end class GreetingServiceImpl

建立一个类来载入Spring容器:
package  springinaction.chapter01.hello;

import  org.springframework.beans.factory.BeanFactory;
import  org.springframework.beans.factory.xml.XmlBeanFactory;
import  org.springframework.core.io.FileSystemResource; // ------(3)
// import java.io.FileInputStream;------------(1)

public  class  HelloApp
{
    
public static void main(String[] args)
    
{
        
try{
            
//BeanFactory factorr = new XmlBeanFactory(new FileInputStream("hello.xml"));----------(2)
            BeanFactory factory = new XmlBeanFactory(new FileSystemResource("hello.xml"));//-----(4)
            GreetingService greetingService = (GreetingService)factory.getBean("greetingService");
            greetingService.sayGreeting();
        }
 catch (Exception ex){
            ex.printStackTrace();
        }

    }
//end main(...)

}
// end class HelloApp
书中原来的代码是( 1 )( 2 ),被我换成了( 3 )( 4 )因为在 Spring2.0 XmlBeanFactory 类已经没有能够接收 FileInputStream 对象的构造函数了,那么作为一般的初学者肯定是从最新版本学起,以至于自己所学的知识不会很快过时或落后。我觉得这一点译者有些不负责任,应该给个说明, 因为在书的开头就给初学者制造这样的障碍,非常打击初学者的积极性。我就是调试了好长时间最后看 XmlBeanFactory 的源代码才弄清楚的,我觉得大家在学习的时候也应该时不时的看看 Spring 的源代码,看看 Spring 的内部到底是怎么实现的。这样对学习非常有好处。
最后给出名为hello.xml文件。
  
<? xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
    
< bean  id  = "greetingService"  
          class 
= "springinaction.chapter01.hello.GreetingServiceImpl" >
        
< property  name  = "greeting" >
            
< value > Buenos Dias! </ value >
        
</ property >
    
</ bean >
</ beans >
上面的一个接口和那个接口的实现就不多说了。主要说说HelloApp类和这个hello.xml文件。由于第一章是作者对Spring的概览,这里也简单说一下HelloApp类和hello.xml文件,这是第二章的主要内容。
Spring中的类主要是一系列的JavaBeans那么在hello.xml文件中<beans>就是这个XML文件的根元素,也是以后任何Spring配置文件的根元素。在hello.xml文件中有这么以行非常关键: <! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >缺少这一行 Spring将无法找到bean(我在练习夏昕所写的《Spring开发指南》时候就是因为少了这一行而郁闷了好长时间的。关于《Spring开发指南》请上满江红开元网站‘http://www.redsaga.com/mambo/’下载。)。bean id = "greetingService"这里的"greetingService"代表的是springinaction.chapter01.hello.GreetingServiceImpl这个类。它(greetingService)可以由你随便命名。peoperty name = “greeting”这里的 property指的是GreetingServiceImpl类中的成员greeting这里的greeting不能随便命名要和类中的成员名一致。<Value>的定义的就是greeting的值。
HelloApp类中,BeanFactory就是Spring容器。他将XML文件载入容器后调用getBean()方法来得到greeting的值。使用这个引用最后调用了sayGreeting()方法。
 
四、理解反向控制( IoC)
反向控制是Spring的核心。Martin Fowler在2004年的一篇文章中通过提问的方式:控制的什么被反转了?他的总结是:获得依赖对象的方式反转了。他还为IOC起了个新名字叫“依赖注入”。关于这篇文章请看:(中文翻译:“我找不到链接了,我记得好像在满江红网站上能下载”;英文原版:http://martinfowler.com/articles/injection.html)
接下来的这节里作者举了一个例子通过用常规的方式和Spring的IOC方式的比较。还讲了企业级应用中的IoC,由于我对EJB一点不懂,所以就不给出代码了。
 
五、应用AOP
在Spring中核心的概念就是IoC和AOP了。IoC使软件组件松散连接成为可能,AOP让你能够捕捉系统中经常使用的功能,把它转化为组建。
AOP经常被定义为一种编程技术,用来在系统中提升业务的分离。系统由很多组件组成,每个组件负责一部分功能。然而,这些组件也经常带有一些除了核心功能之外的附带功能。这些功能相互交叉给你的代码引入了双重复杂性。
AOP帮助我们将这些服务模块化,并把他们声明式地应用在需要他们的地方。结果是这些组件更加专注于自身业务,完全不知道其他涉及到的系统功能和服务。这样就降低了负杂性。下面给出一个接近书中作者例子的代码(本来这个例子我不想实现,看看书理解了算了,最后又一想还是动动手吧,眼过千遍不如手过一边。):关于这个例子虽然能运行但也只是个例子,功能没有填充。关于XML文件和AOP也不想多说,这在第二章和第三章都有详细的说明。
 
package  springinaction.chapter01.iocapp;

public  interface  Knight
{
    
public Object embarkOnQuest();
}
// end interface Knight

package  springinaction.chapter01.iocapp;

public  interface  Quest
{
    
public abstract Object embark();//书中的QuestException就不定义了
}
// end interface Quest

package  springinaction.chapter01.iocapp;

public  class  HolyGrailQuest  implements  Quest
{
    
public HolyGrailQuest()
    
{
        
//do something....
    }

    
    
public Object embark()
    
{
        
return new HolyGrailQuest();
    }
//end embark()
    
}
// end class HolyGrailQuest

package  springinaction.chapter01.iocapp;

public  class  KnightOfTheRoundTable  implements  Knight
{
    
private String name;
    
private Quest quest;
    
    
public KnightOfTheRoundTable(String name)
    
{
//        quest = new HolyGrailQuest();
        this.name = name;
        System.out.println(
this.name);
    }

    
    
public HolyGrailQuest embarkOnQuest()
    
{
        
return (HolyGrailQuest)quest.embark();
    }
//end embarkOnQuest()
    
    
public void setQuest(Quest quest)
    
{
        
this.quest = quest;
    }

    
}
// end class KnightOfTheRoundTable

package  springinaction.chapter01.iocapp;

import  java.lang.reflect.Method;
import  org.springframework.aop.MethodBeforeAdvice;
import  org.apache.log4j.Logger;

public  class  MinstrelAdvice  implements  MethodBeforeAdvice
{
    
public MinstrelAdvice()
    
{
        
//do something....
    }

    
    
public void before(Method method, Object[] args, Object target)
    
{
        Knight knight 
= (Knight)target;
        Logger song 
= Logger.getLogger(target.getClass());
        song.debug(
"Brave" + " did " + method.getName());
    }


}

 
 
<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
    
< bean  id  = "quest"
          class 
= "springinaction.chapter01.iocapp.HolyGrailQuest" >
    
</ bean >
    
    
< bean  id  = "knightTarget"
          class 
= "springinaction.chapter01.iocapp.KnightOfTheRoundTable" >
        
< constructor-arg >
            
< value > Bedivere </ value >
        
</ constructor-arg >
        
< property  name  = "quest" >
            
< ref  bean  = "quest" />
        
</ property >
    
</ bean >
    
    
< bean  id  = "minstrel"
          class  
= "springinaction.chapter01.iocapp.MinstrelAdvice" >
    
</ bean >
    
    
< bean  id  = "knight"
          class 
= "org.springframework.aop.framework.ProxyFactoryBean" >
          
< property  name ="proxyInterfaces" >
              
< list >
                  
< value > com.springinaction.chapter01.iocapp.Knight </ value >
              
</ list >
          
</ property >
          
< property  name ="interceptorName" >
              
< list >
                  
< value > minstrel </ value >
              
</ list >
          
</ property >
          
          
< property  name ="target" >
              
< ref  bean  ="knightTarget" />
          
</ property >
    
</ bean >
</ beans >
 
package  springinaction.chapter01.iocapp;

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

public  class  KnightApp
{
    
public static void main(String[] args)
    
{
        BeanFactory factory 
= new XmlBeanFactory(new FileSystemResource("knight.xml"));
        KnightOfTheRoundTable knight 
= (KnightOfTheRoundTable)factory.getBean("knightTarget");
        knight.embarkOnQuest();
    }

}
// end class KnightApp

六、 Spring 比较
在本节中作者重点对Spring和EJB进行了比较,列出了二者的优缺点,并简单给出了何时使用Spring何时使用EJB的建议。还简单介绍了若干其他容器和框架:
l         PicoContaniner:一个最小的轻量级容器,他提供了构造注入和设置注入两种IoC方式。
l         HiveMind:是一个相对而言比较新的IoC容器。(http://jakarta.apache.org/hivemind/)
l         Avalon:最早开发的IoC容器。(http://avalon.apache.org/closed.html)
Web框架有Struts,WebWork,Tapestry,持久层框架有:Hibernate、JDO、OJB、和iBATIS等等。
 
七、小结
通过该章前面简单的了解和实践,我们已经对Spring提供什么功能有了一个好的初步的认识。Spring的目的是简化J2EE开发;Spring的核心概念是IoC和AOP;Spring提供了几种对持久层技术的支持;Spring的事物管理支持是对持久层集成的补充;Spring提供了与各种其他J2EE服务的集成;Spring支持多种视图技术。从第二章开始,将逐个学习Spring的核心技术。
 

你可能感兴趣的:(spring,AOP,bean,ejb,IOC,action)