Spring入门简介

来源:互联网 发布:idea uml生成java代码 编辑:程序博客网 时间:2024/06/04 18:37

Spring作为一个相对轻量级的框架,可以说是企业级应用的必备元素之一。

1  什么是Spring

Spring是一个符合J2EE标准的开发框架,同时是一个以IoC,即“依赖注入”为核心的容器。Spring框架可以独自实现开发人员的各种设想,同时,也能够与现有的被广泛应用的开源框架相整合,使得开发人员能够更加方便地构筑程序。

Spring的主要功能包括:依赖注入,面向切面编程。这两大功能后续会详细介绍。而Spring主推的是MVC架构,Dispatcher负责处理转发消息和数据,Controler负责处理数据,Viewer负责处理呈现。Spring本身是多层的多模块的,一些模块或者层次可以用别的框架或容器代替,比如Struts替代Spring的MVC。

Spring最大的优点在于,开发人员可以更加模块化工作,如何整合依赖关系可以独立实现,代码的耦合性大大降低。而且,Spring不需要每个开发人员都熟悉掌握,开发人员负责的模块很可能不需要写入与Spring相关的代码,开发人员专注完成自己的模块,最后由专人统一整合即可。

2  Spring的整体架构

Spring的整体架构如下图:


Spring的Bean是最为重要也是最为出名的设计,Bean之于Spring可以类比于面向对象语言的对象,Spring框架是通过Bean划分模块,即将代码块包入Bean中实现管理的。需要注意的一点是Spring推荐的编程思想是面向接口思想而不是面向对象思想。

Spring的Context可以类比为环境变量,或者说Bean运行的上下文,注意控制Bean所在的环境。Context实际上是Spring的反向控制容器,通过配置文件控制Bean的依赖关系,详细内容见第3节。

Core则可以理解为utilities,是一系列基础接口的集合,处理整个框架遇到的各种事情。Core最出色的地方在于抽象出了Resource接口,封装了各种可能利用到的资源。每个Bean都可能需要用到Core中的接口。

更为复杂的架构图如下:


3  Spring的反向控制(IoC)

3.1  POJO

POJO指的是简单的Java类,包括数据项,和数据项的Get和Set方法。

3.2  反向控制

通常的面向对象语言例子当中,我们遇到新的数据元素,需要通过new的方式创建,并且有的情况下需要知道传给构造函数的参数是什么,在哪里。

假如程序猿A需要编写的模块涉及了程序猿B的接口,那么这里可能出现各种复杂问题。反向控制指的是,当A编程时,不去管B的接口中有什么,甚至不需要知道是B在编写自己需要的模块,只需要完成自己的工作,最后由配置文件决定A的模块调用哪个接口。

比如,现在有一个类Animal,Animal有一个行为:Bark(),不使用容器的代码大概如下:

public void sound(){

Animal An=new Animal();

An.Bark();

}

而使用Spring容器的代码可以是如下:

public class sound(){

    public Animal An;

    public sound(Animal A){

            this.An=A;

    }

    public void setAn(Animal A){

            this.An=A;

    }

    public void shout(){

        An.Bark();

    }

看起来使用Spring的方法是比较麻烦的,但仔细分析一下不使用Spring的代码,为了弄出声音,我们需要知道Animal的构造函数,如果Animal继承出Cat和Dog类,那么Sound也要再次重新编写;反而观之,Spring不关心Animal是如何而来,只需要传入或称注入一个Animal的类(或是接口),甚至可以在Animal被继承之后继续使用。

而sound类需要的Animal是怎么被传入的呢?这就需要Spring的配置功能起作用了,配置文件applicationContext.xml里写上:

    <bean id="Animal" class="Animal"> 
    <bean id="sound" class="sound"> 
        <property name="Animal"> 
            <ref bean="Animal"/>

这样,程序就可以按图索骥,获取到Animal了。为了让这两部分跑起来,需要写个main函数:

public static void main(String[] args)  

        ApplicationContext context =  
            New ClassPathXmlApplicationContext("applicationContext.xml"); 
        sound soundA = (sound )context.getBean("sound"); 
        sound.shout(); 
}

当我们的Animal有了新的bark方式的时候,sound部分不用改;当Animal有了继承者的时候,只需要改下配置文件即可。

4  Spring的面向切面编程(AOP)

AOP技术要解决的问题是,项目会有一些附加功能,但是附加功能又必须有个方法嵌到各个模块当中,而又不希望各个模块开发人员对此写额外代码。最典型的是日志系统,每个模块都可能需要记录下日志,但是日志又应该是一个独立模块,并且能够在最后装配到一起。Spring的AOP功能能够很好地处理这种情景。

Spring的AOP模块包括3个概念:advice,pointcut和advisor。advice是想向各个程序内部注入的代码。pointcut定义了要注入advice的位置。advisor是pointcut和advice的装配器,执行将advice注入主程序中特定位置的操作。

继续上面的例子,现在需要通过记录下Animal叫的时间,观察Animal的习性,那么需要增加一个log接口:

public class LogAdvice implements MethodBeforeAdvice  

    public void before(Method arg0, Object[] arg1, Object arg2)throws Throwable  
    { 
        System.out.println("Animal barked~"); 
    } 
}

这里实现了MethodBeforeAdvice,MethodBeforeAdvice是Spring类库提供的方法,类似的还有AfterReturningAdvice,分别是在各个程序之前、之后运行log实现的接口。

为了每次运行Bark()之前都运行log并记录,需要在applicationContext.xml里重新写入一些配置项:

    <bean id="Animal " class="Animal "/> 
    <bean id="sound" class="sound"> 
        <property name="Animal "> 
            <ref bean="AnimalProxy"/> 
    <bean id="LogAdvice" class="LogAdvice"/> 
    <bean id="SpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> 
        <property name="proxyInterfaces"> 
            IAnimal
        <property name="interceptorNames"> 
                LogAdvice 
        <property name="target"> 
            <ref local="Animal"/>

这里有了一个叫IAnimal的接口(没有将代码放上来,原因是代码简单且无用),有了IAnimal接口的实现叫Animal,有了一个需要注入的程序叫LogAdvice,有了一个调用Animal这个接口实现类的sound类,上面的代码首先将sound、LogAdvice和Animal声明,然后声明一个Proxy,写好3者之间的关系,下面是Proxy的三个属性的意思:

proxyInterfaces,这里可以是List,写的是IAnimal之类的接口,因为Spring是面向接口编程的,所以需要先将接口声明出来。

Target是注入的目标:Animal;

interceptorNames是被注入的代码。

这样,每次Animal被调用之前,都会执行LogAdvice。

可以在bean LogAdvice里添加正则表达式,假设工程项目叫做springaop,位于company之下:

<property name="pattern"> 
      <value>com/.company/.springaop/.IAnimal/.Bark</value> 
    </property> 

这样,LogAdvice会自动判断Bark()的调用,并在调用前执行Log。

5  Spring的事务管理

5.1  基于XML的事务管理

如果项目的命名比较统一,那么可以简单地利用XML规则匹配,进而控制事务。

5.2  annotation形式事务管理

首先在Spring的XML文件加上:

<tx:annotation-driven transaction-manager="transactionManager"/>

然后在Java文件就可以用以下形式了:

@Service    
@Transactional(propagation = Propagation.REQUIRED)

事务管理可以有添加原子操作,提交事务,滚回操作等等,很实用。

6  几点思考

Spring的annotation方法已经非常完善了,包括了MVC和许多种类型,并且能够方便地使用。

在数据的前后端传递上,也可以支持各种方法,包括非常自由的url:

*/{Id}        @PathVariable int Id

或者是:

@RequestMapping(value="/add", method=RequestMethod.POST)
@ResponseBody
public boolean add(@RequestBody String data)

这样可以不用显式传递数据,或显式的数据很少,另外一种传统的Servlet方式也支持:

@RequestMapping(value="/add", method=RequestMethod.POST)
@ResponseBody
public String addCargoTrack(@RequestParam("id") String id,HttpServletRequest request){};

而且,Spring提供了一站式的服务,开发人员可以只去翻阅Spring的相关资料就能完成开发;同时,Spring又没有强制使用自己的组件,而是每个组成部分都能过使用现有的其它开源框架,比如开发团队很熟悉struts,那么也可以用熟悉的结构实现功能。

0 0
原创粉丝点击