- 浏览: 325150 次
- 性别:
- 来自: 天津
文章分类
最新评论
-
杞哈哈:
你好。我是个新手。去官网也没下载下来那个服务器端。有现成的吗? ...
初探JAXER -
sl514:
http://www.bejson.com
JSON学习 -
sl514:
你可以使用JSON在线格式化、校验、视图工具 http://w ...
JSON学习 -
srg23:
好像在FF下不兼容。
教你怎么使网页全部变成灰色的! -
vera_sq:
你的方法我试过,还是不行呢!
AJAX技术使用XMLHttpRequest对象传递参数的中文乱码问题
一、 Spring诞生
Spring是一个开源框架,目前在开源社区的人气很旺,被认为是最有前途的开源框架之一。她是由Rod Johnson创建的,她的诞生是为了简化企业级系统的开发。说道Spring就不得不说EJB,因为Spring在某种意义上是EJB的替代品,她是一种轻量级的容器。用过EJB的人都知道EJB很复杂,为了一个简单的功能你不得不编写多个Java文件和部署文件,他是一种重量级的容器。也许你不了解EJB,你可能对“轻(重)量级”和“容器”比较陌生,那么这里我简单介绍一下。
1、什么是容器
“容器”,这个概念困扰我好久。从学习Tomcat开始就一直对此感到困惑。感性的来讲,容器就是可以用来装东西的物品。那么在编程领域就是指用来装对象(OO的思想,如果你连OO都不了解,建议你去学习OO先)的对象。然而这个对象比较特别,它不仅要容纳其他对象,还要维护各个对象之间的关系。这么讲可能还是太抽象,来看一个简单的例子:
代码片断1:
public class Container { public void init() { Speaker s = new Speaker(); Greeting g = new Greeting(s); } }
可以看到这里的Container类(容器)在初始化的时候会生成一个Speaker对象和一个Greeting对象,并且维持了它们的关系,当系统要用这些对象的时候,直接问容器要就可以了。这就是容器最基本的功能,维护系统中的实例(对象)。如果到这里你还是感到模糊的话,别担心,我后面还会有相关的解释。
2、轻量级与重量级
所谓“重量级”是相对于“轻量级”来讲的,也可以说“轻量级”是相对于重量级来讲的。在Spring出现之前,企业级开发一般都采用EJB,因为它提供的事务管理,声明式事务支持,持久化,分布计算等等都“简化”了企业级应用的开发。我这里的“简化”打了双引号,因为这是相对的。重量级容器是一种入侵式的,也就是说你要用EJB提供的功能就必须在你的代码中体现出来你使用的是EJB,比如继承一个接口,声明一个成员变量。这样就把你的代码绑定在EJB技术上了,而且EJB需要JBOSS这样的容器支持,所以称之为“重量级”。
相对而言“轻量级”就是非入侵式的,用Spring开发的系统中的类不需要依赖Spring中的类,不需要容器支持(当然Spring本身是一个容器),而且Spring的大小和运行开支都很微量。一般来说,如果系统不需要分布计算或者声明式事务支持那么Spring是一个更好的选择。
二、 几个核心概念
在我看来Spring的核心就是两个概念,反向控制(IoC),面向切面编程(AOP)。还有一个相关的概念是POJO,我也会略带介绍。
1、POJO
我所看到过的POJO全称有两个,Plain Ordinary Java Object,Plain Old Java Object,两个差不多,意思都是普通的Java类,所以也不用去管谁对谁错。POJO可以看做是简单的JavaBean(具有一系列Getter,Setter方法的类)。严格区分这里面的概念没有太大意义,了解一下就行。
2、 IoC
IoC的全称是Inversion of Control,中文翻译反向控制或者逆向控制。这里的反向是相对EJB来讲的。EJB使用JNDI来查找需要的对象,是主动的,而Spring是把依赖的对象注入给相应的类(这里涉及到另外一个概念“依赖注入”,稍后解释),是被动的,所以称之为“反向”。先看一段代码,这里的区别就很容易理解了。
代码片段2:
public void greet() { Speaker s = new Speaker(); s.sayHello(); }
代码片段3:
public void greet() { Speaker s = (Speaker)context.lookup("ejb/Speaker"); s.sayHello(); }
代码片段4:
public class Greeting { public Speaker s; public Greeting(Speaker s) { this.s = s; } public void greet() { s.sayHello(); } }
我们可以对比一下这三段代码。其中片段2是不用容器的编码,片段3是EJB编码,片段4是Spring编码。结合代码片段1,你能看出来Spring编码的优越之处吗?也许你会觉得Spring的编码是最复杂的。不过没关系,我在后面会解释Spring编码的好处。
这里我想先解释一下“依赖注入”。根据我给的例子可以看出,Greeting类依赖Speaker类。片段2和片段3都是主动的去获取Speaker,虽然获取的方式不同。但是片段4并没有去获取或者实例化Speaker类,而是在greeting函数中直接使用了s。你也许很容易就发现了,在构造函数中有一个s被注入(可能你平时用的是,传入)。在哪里注入的呢?请回头看一下代码片段1,这就是使用容器的好处,由容器来维护各个类之间的依赖关系(一般通过Setter来注入依赖,而不是构造函数,我这里是为了简化示例代码)。Greeting并不需要关心Speaker是哪里来的或是从哪里获得Speaker,只需要关注自己分内的事情,也就是让Speaker说一句问候的话。
3、 AOP
AOP全称是Aspect-Oriented Programming,中文翻译是面向方面的编程或者面向切面的编程。你应该熟悉面向过程的编程,面向对象的编程,但是面向切面的编程你也许是第一次听说。其实这些概念听起来很玄,说到底也就是一句话的事情。
现在的系统往往强调减小模块之间的耦合度,AOP技术就是用来帮助实现这一目标的。举例来说,假如上文的Greeting系统含有日志模块,安全模块,事务管理模块,那么每一次greet的时候,都会有这三个模块参与,以日志模块为例,每次greet之后,都要记录下greet的内容。而对于Speaker或者Greeting对象来说,它们并不知道自己的行为被记录下来了,它们还是像以前一样的工作,并没有任何区别。只是容器控制了日志行为。如果这里你有点糊涂,没关系,等讲到具体Spring配置和实现的时候你就明白了。
假如我们现在为Greeting系统加入一个Valediction功能,那么AOP模式的系统结构如下:
G|RET|TIN|G
V|ALE|DIT|ION
| | |
日志 安全 事务
这些模块是贯穿在整个系统中的,为系统的不同的功能提供服务,可以称每个模块是一个“切面”。其实“切面”是一种抽象,把系统不同部分的公共行为抽取出来形成一个独立的模块,并且在适当的地方(也就是切入点,后文会解释)把这些被抽取出来的功能再插入系统的不同部分。
从某种角度上来讲“切面”是一个非常形象的描述,它好像在系统的功能之上横切一刀,要想让系统的功能继续,就必须先过了这个切面。这些切面监视并拦截系统的行为,在某些(被指定的)行为执行之前或之后执行一些附加的任务(比如记录日志)。而系统的功能流程(比如Greeting)并不知道这些切面的存在,更不依赖于这些切面,这样就降低了系统模块之间的耦合度。
三、 Spring初体验
这一节我用一个具体的例子Greeting,来说明使用Spring开发的一般流程和方法,以及Spring配置文件的写法。
首先创建一个Speaker类,你可以把这个类看做是POJO。
代码片段5:
public class Speaker { public void sayHello() { System.out.println("Hello!"); } }
再创建一个Greeting类。
代码片段6:
public class Greeting { private Speaker speaker; public void setSpeaker(Speaker speaker) { this.speaker = speaker; } public void greet() { speaker.sayHello(); } }
然后要创建一个Spring的配置文件把这两个类关联起来。
代码片段7(applicationContext.xml):
<"1.0" encoding="UTF-8"?>
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
"Speaker" class="Speaker">
"Greeting" class="Greeting">
"speaker">
"Speaker"/>
要用Spring Framework必须把Spring的包加入到Classpath中,我用的是Eclipse+MyEclipse,这些工作是自动完成的。推荐用Spring的配置文件编辑器来编辑,纯手工编写很容易出错。我先分析一下这个xml文件的结构,然后再做测试。从节点开始,先声明了两个,第二个bean有一个speaker属性(property)要求被注入,注入的内容是另外一个bean Speaker。这里的命名是符合JavaBean规范的,也就是说如果是speaker属性,那么Spring容器就会调用setSpeaker()来注入这个属性。是reference的意思,表示引用另外一个bean。
下面看一段简单的测试代码:
代码片段8:
public static void main(String[] args) { ApplicationContext context = New ClassPathXmlApplicationContext("applicationContext.xml"); Greeting greeting = (Greeting)context.getBean("Greeting"); greeting.greet(); }
这段代码很简单,如果你上文都看懂了,那么这里应该没有问题。值得注意的是Spring有两种方式来创建容器(我们不再用上文我们自己编写的Container),一种是ApplicationContext,另外一种是BeanFactory。ApplicationContext更强大一些,而且使用上两者没有太大区别,所以一般说来都用ApplicationContext。Spring容器帮助我们维护我们在配置文件中声明的Bean以及它们之间的依赖关系,我们的Bean只需要关注自己的核心业务。
四、 面向接口的编程
看了这么多,也许你并没有觉得Spring给开发带来了很多便利。那是因为我举的例子还不能突出Spring的优越之处,接下来我将通过接口编程来体现Spring的强大。
假如现在要求扩展Greeting的功能,要让Speaker用不同的语言来问候,也就是说有不同的Speaker,比如ChineseSpeaker, EnglishSpeaker。那么对上文提到的三种编码方式(代码片段2、3、4)分别加以修改,你会发现很麻烦。假如下次又要加入一个西班牙语,又得重复劳动。很自然的会考虑到使用一个ISpeaker接口来简化工作,,更改后的代码如下(这里没有列出接口的相关代码,我想你应该明白怎么写):
代码片段9:
public void greet() { ISpeaker s = new ChineseSpeaker(); s.sayHello(); }
代码片段10:
public void greet() { ISpeaker s = (ISpeaker)context.lookup("ejb/ChineseSpeaker"); s.sayHello(); }
代码片段11:
public class Greeting { public ISpeaker s; public Greet(ISpeaker s) { this.s = s; } public void greet() { s.sayHello(); } }
对比三段代码,你会发现,第一种方法还是把具体的Speaker硬编码到代码中了,第二中方法稍微好一点,但是没有本质改变,而第三种方法就不一样了,代码中并没有关于具体Speaker的信息。也就是说,如果下次还有什么改动的话,第三种方法的Greeting类是不需要修改,编译的。根据上文Spring的使用介绍,只需要改动xml文件就能给Greeting注入不同的Speaker了,这样代码的扩展性是不是提高了很多?
关于Spring的接口编程还有很多东西可以去挖掘,后文还会提到有关Spring Proxy的接口编程,我这里先介绍这么多,有兴趣话可以去google更多的资料。
五、 应用Spring中的切面
Spring生来支持AOP,首先来看几个概念:
1、 切面(Aspect):切面是系统中抽象出来的的某一个功能模块,上文已经有过介绍,这里不再多说。
2、 通知(Advice):通知是切面的具体实现。也就是说你的切面要完成什么功能,具体怎么做就是在通知里面完成的。这个名称似乎有点让人费解,等后面看了代码就明白了。
3、 切入点(Pointcut):切入点定义了通知应该应用到系统的哪些地方。Spring只能控制到方法(有的AOP框架可以控制到属性),也就是说你能在方法调用之前或者之后选择切入,执行额外的操作。
4、 目标对象(Target):目标对象是被通知的对象。它可以是任何类,包括你自己编写的或者第三方类。有了AOP以后,目标对象就只需要关注自己的核心业务,其他的功能,比如日志,就由AOP框架支持完成。
5、 代理(Proxy):简单的讲,代理就是将通知应用到目标对象后产生的对象。Spring在运行时会给每个目标对象生成一个代理对象,以后所有对目标对象的操作都会通过代理对象来完成。只有这样通知才可能切入目标对象。对系统的其他部分来说,这个过程是透明的,也就是看起来跟没用代理一样。
我为了简化,只介绍这5个概念。通过这几个概念应该能够理解Spring的切面编程了。如果需要深入了解Spring AOP的话再去学习其他概念也很快的。
下面通过一个实际的例子来说明Spring的切面编程。继续上文Greeting的例子,我们想在Speaker每次说话之前记录Speaker被调用了。
首先创建一个LogAdvice类:
代码片段12:
public class LogAdvice implements MethodBeforeAdvice { public void before(Method arg0, Object[] arg1, Object arg2)throws Throwable { System.out.println("Speaker called!"); } }
这里涉及到一个类,MethodBeforeAdvice,这个类是Spring类库提供的,类似的还有AfterReturningAdvice等等,从字面就能理解它们的含义。先不急着理解这个类,我稍后解释。我们继续看如何把这个类应用到我们的系统中去。
代码片段13:
"Speaker" class="Speaker"/>
"Greeting" class="Greeting">
"speaker">
"SpeakerProxy"/>
"LogAdvice" class="LogAdvice"/>
"SpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
"proxyInterfaces">
ISpeaker
"interceptorNames">
LogAdvice
"target">
"Speaker"/>
可以看到我们的配置文件中多了两个bean,一个LogAdvice,另外一个SpeakerProxy。LogAdvice很简单。我着重分析一下SpeakerProxy。这个Bean实际上是由Spring提供的ProxyFactoryBean实现。下面定义了三个依赖注入的属性。
1、 proxyInterfactes:这个属性定义了这个Proxy要实现哪些接口,可以是一个,也可以是多个(多个的话,要用list标签)。我前面讲过Proxy是在运行是动态创建的,那么这个属性就告诉Spring创建这个Proxy的时候实现哪些接口。
2、 interceptorNames:这个属性定义了Proxy被切入了哪些通知,这里只有一个LogAdvice。
3、 target:这个属性定义了被代理的对象。在这个例子中target是Speaker。
这样的定义实际上约束了被代理的对象必须实现一个接口,这与上文讲的面向接口的编程有点类似。其实可以这样理解,接口的定义可以让系统的其他部分不受影响,以前用ISpeaker接口来调用,现在加入了Proxy还是一样的。但实际上内容已经不一样了,以前是Speaker,现在是一个Proxy。而target属性让proxy知道具体的方法实现在哪里。Proxy可以看作是target的一个包装。当然Spring并没有强制要求用接口,通过CGLIB(一个高效的代码生成开源类库)也可以直接根据目标对象生成子类,但这种方式并不推荐。
我们还像以前一样的测试我们的Greeting系统,测试代码和代码片段8是一样的。运行结果如下:
Speaker called!
Hello!
看到效果了吧!而且你可以发现,我们加入Log功能并没有改变以前的代码,甚至测试代码都没有改变,这就是AOP的魅力所在!我们更改的只是配置文件。
下面解释一下刚才落下的MethodBeforeAdvice。关于这个类我并不详细介绍,因为这涉及到Spring中的另外一个概念“连接点(Jointpoint)”,我详细介绍一个before这个方法。这个方法有三个参数arg0表示目标对象在哪个点被切入了,既然是MethodBeforeAdvice,那当然是在Method之前被切入了。那么arg0就是表示的那个Method。第二个参数arg1是Method的参数,所以类型是Object[]。第三个参数就是目标对象了,在Greeting例子中arg2的类型实际上是Speaker。
在Greeting例子中,我们并没有指定目标对象的哪些方法要被切入,而是默认切入所有方法调用(虽然Speaker只有一个方法)。通过自定义Pointcut,可以控制切入点,我这里不再介绍了,因为这并不影响理解Spring AOP,有兴趣的话去google一下就知道了。
六、实战Spring
虽然这部分取名为“实战Spring”,但实际上我并不打算在这里介绍实际开发Spring的内容,因为我写这篇文章的目的是介绍Spring的概念和用Spring开发的思路,而不是有关Spring的实践和详细介绍。文中介绍的内容和用Spring做实际开发还相去甚远。之所以取名“实战Spring”是我觉得理解了上文讲的内容以后,可以开始为深入学习Spring和学习如何在项目中应用Spring了。
要系统的学习Spring还是需要阅读一本详细介绍Spring的书,我推荐Spring in Action,因为我看的就是这本书。希望这篇文章能为你系统的学习Spring扫除一些障碍。
发表评论
-
java版本的escape和unescape函数
2008-08-01 10:54 1201java版本的escape和unescape函数 cl ... -
java中的URLEncoder和URLDecoder类
2008-07-11 00:31 1150/* 网页中的表单使用POST方法提交时,数据内容的 ... -
JDOM处理XML快速上手
2008-07-11 00:12 1374在 JDOM 中,XML 元素就 ... -
JDOM 介绍及使用指南
2008-07-11 00:10 1153一、JDOM 简介JDOM是一个开源项目,它基于树型结构,利用 ... -
Java生成UUID
2008-07-01 16:15 1843UUID(Universally Unique Identif ... -
JSON 基础
2008-06-26 10:45 1007JSON 基础简单地说,JSON 可以将 JavaScript ... -
DatabaseMetaData
2008-05-07 14:19 1180package com.rongji.demo; import ... -
JspSmart之upload组件源码及使用
2008-04-23 16:24 2032一、安装篇 jspsmartupload是由www ... -
Hibernate的主键生成机制
2008-04-10 11:38 1125配置Hibernate的主键生成 ... -
session与cookie关系
2008-04-10 11:36 3222具体来说cookie机制采用的是在客户端保持状态的方案。它是在 ... -
cookie和session
2008-04-10 11:30 796一、cookie机制和session机制的区别******** ... -
有用的国外开源项目网址
2008-04-10 11:29 2457sourceforge http://www.sourcefo ... -
hibernate包作用详解
2008-04-10 11:27 860Hibernate一共包括了23个ja ... -
servlet中 web.xml的配置问题!
2008-04-10 10:56 1232表单中: <form action="/工程名 ... -
页面乱码解决4种方案
2008-04-10 09:48 1701下边提供4种不同情况的乱码解决方案,基本上包括了web开发中出 ... -
jsp编码讨论
2008-04-09 18:01 1079为每个jsp页面设置了其 ... -
JSP中tomcat的SQL Server2000数据库连接池的配置
2008-04-09 17:38 1250JSP中tomcat的SQL Server2000数据库连接池 ... -
Java中ResultSet对象里的问题
2008-02-27 12:58 1765public static void main(String ...
相关推荐
根据提供的文件信息,我们可以深入探讨Spring框架的相关知识点。尽管标题和描述相对简略,但从“传智播客_Spring ...希望本文能帮助读者更好地理解Spring框架的核心概念和应用场景,为后续的学习和实践打下坚实的基础。
Rod Johnson在其著作《Expert One-to-One J2EE Design and Development》中对Java EE框架的臃肿和低效提出质疑,并着手探索更加轻量级的开发框架。这一探索的成果便是interface21框架,而Spring正是在此基础上进一步...
综上所述,从Spring 2.0升级到Spring 3.0.5不仅意味着替换旧的jar包,更是采纳了一整套更加先进和完善的开发框架。这个过程可能会涉及到代码和配置的调整,但最终会带来更高的开发效率和更好的应用性能。对于开发者...
Spring Framework是Java开发领域中广泛使用的开源框架,它以其模块化、松耦合的设计理念,为开发者提供了构建高质量企业级应用的强大支持。4.3.6.RELEASE是Spring Framework的一个稳定版本,它在之前版本的基础上...
### Spring框架的设计理念和设计模式分析 #### 一、Spring框架概述 ...总之,Spring框架的设计理念和技术实现为现代Java应用开发提供了强有力的支撑,同时也为我们理解和设计高质量的软件系统提供了宝贵的参考。
员工工资管理系统是一款典型的企业级应用,它采用先进的技术栈,包括Spring MVC、Spring、Hibernate和Maven,为企业的薪酬管理提供了一套高效、稳定的解决方案。这些框架的组合使用,能够实现系统的模块化、自动化...
整体来看,该框架的设计理念和实现技术都体现了当前Web开发的先进性和实践性。其对Spring框架的深入挖掘和对MVC模式的创新应用,使得该框架在提供高效开发的同时,也保持了高度的灵活性和可扩展性。通过这种方式,...
本文将深入探讨一个基于Java的、利用Spring MVC、Spring 2.0和Hibernate 3.0框架开发的人力资源管理系统,帮助读者理解如何通过这些技术构建高效、稳定的企业级应用。 一、Spring MVC框架 Spring MVC是Spring框架的...
SSH框架,全称为Struts、Spring和Hibernate,是Java Web开发中的一个经典组合,用于构建高效、可维护的Web应用程序。这个框架集合充分利用了各组件的优势,为开发者提供了强大的功能和灵活的架构。 Struts是MVC...
Spring框架是Java开发领域中的一款核心工具,以其模块化、灵活性和广泛的社区支持而闻名。...掌握Spring框架的使用,不仅能够提升开发效率,还能更好地理解和实践面向切面编程、依赖注入等先进的软件设计思想。
1. 源码:供开发者阅读和学习,理解Spring的实现原理。 2. JAR文件:包含Spring的核心库和其他模块,可以在项目中直接引用。 3. 文档:包括用户指南、参考手册和API文档,帮助开发者了解如何使用Spring的各种功能。 ...
总的来说,基于Java的LLM应用开发框架是AI技术与传统软件工程相结合的产物,它降低了开发者的门槛,使得更多的人能够利用先进的NLP技术构建自己的应用。无论是企业级的信息检索系统,还是个人的文本生成项目,都可以...
Spring框架本身是一个全面的企业级应用开发框架,提供了依赖注入(DI)和面向切面编程(AOP)的核心功能。依赖注入简化了对象之间的关系,使代码更易于测试和维护。AOP则允许开发者定义横切关注点,如日志、事务管理...
接下来是Spring框架,它是一个全面的企业级应用开发框架,提供了依赖注入(DI)、面向切面编程(AOP)、事务管理等功能。在本项目中,Spring用于管理各个组件的生命周期,实现bean的自动装配,并提供事务控制,确保...
**Spring** 是一个全面的Java企业级应用开发框架,它不仅支持MVC模式,还提供了依赖注入(DI)和面向切面编程(AOP)等核心功能。在SSH框架中,Spring作为服务层的容器,管理对象的生命周期和依赖关系。例如,它可以...
Spring框架是中国最流行的Java企业级应用开发框架,它以其模块化、灵活性和强大的功能而闻名。这个压缩包包含了Spring框架的3.2.0.RELEASE版本,这是一个在2012年发布的稳定版本,尽管现在有更先进的版本,但3.2.0...
《Spring in Action》第四版是由Craig Walls撰写,张卫滨翻译的一本权威Spring框架实战教程。...阅读《Spring in Action》第四版,你将能够深入理解Spring框架的工作原理,以及如何有效地将其应用到实际项目中。
综上所述,Spring 2.5.6版本提供了强大的bean管理、上下文支持、核心工具和Web开发框架。虽然现在已经有了更先进的版本,但理解这些基础概念对于掌握Spring框架的整体工作原理至关重要。在实际开发中,这些组件共同...