??xml version="1.0" encoding="utf-8" standalone="yes"?>激情久久久久,国产一区在线播放,国产一区不卡http://www.aygfsteel.com/hongyunxp/zh-cnWed, 18 Jun 2025 09:51:27 GMTWed, 18 Jun 2025 09:51:27 GMT60用Spring AOP实现开发中松散耦合http://www.aygfsteel.com/hongyunxp/archive/2007/05/20/118699.html徐洪?/dc:creator>徐洪?/author>Sun, 20 May 2007 08:35:00 GMThttp://www.aygfsteel.com/hongyunxp/archive/2007/05/20/118699.htmlhttp://www.aygfsteel.com/hongyunxp/comments/118699.htmlhttp://www.aygfsteel.com/hongyunxp/archive/2007/05/20/118699.html#Feedback0http://www.aygfsteel.com/hongyunxp/comments/commentRss/118699.htmlhttp://www.aygfsteel.com/hongyunxp/services/trackbacks/118699.html  摘要 面向斚w~程QAOPQ是面向对象~程QOOPQ的一U扩展技术,能够很好的解x切关注点问题以及相关的设计难题来实现松散耦合。Spring AOP ?AOP 技术的一U实现。本文介l了AOP 概念Q然后详l讨Z如何利用Spring AOP 开发AOP E序Q最后展望了Spring AOP 的前景?br>
  关键?/strong> AOP Spring AOP Java

  引言

  AOPQAspected Oriented ProgrammingQ是一U新兴的~程技术。它可以解决OOP和过E化Ҏ不能够很好解决的横切QcrosscutQ问题,如:事务、安全、日志等横切x。当未来pȝ变得来复杂,横切x点就成ؓ一个打问题的时候,AOP可以很L的解x切关注点q个问题Q得AOP~程成ؓ。Spring 是基于J2EE的轻量开源开发框Ӟ其中Spring AOPlg实现了面向方面编E?br>
  AOP 概述

  面向斚w~程 (AOP) 提供从另一个角度来考虑E序l构以完善面向对象编E(OOPQ?面向对象应用程序分解成各个层次的对象,而AOP程序分解成各个斚w或者说x?。这使得可以模块化诸如事务管理等q些横切多个对象的关注点?

  1、AOP 基本概念

  斚wQAspectQ: 一个关注点的模块化Q这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切x点例子。方面用Spring?Advisor或拦截器实现?br>
  q接点(JoinpointQ? E序执行q程中明的点,如方法的?用或特定的异常被抛出?br>
  通知QAdviceQ? 在特定的q接点,AOP框架执行的动作。各U类 型的通知包括“around”?#8220;before”?#8220;throws”通知。通知cd在下面讨论。许多AOP框架 包括Spring都是以拦截器做通知模型Q维护一?#8220;围绕”q接点的拦截器链?br>
  切入点(PointcutQ? 指定一个通知被引发的一pdq接?的集合。AOP框架必须允许开发者指定切入点Q例如,使用正则表达式?br>
  引入QIntroductionQ? dҎ或字D到被通知的类?Spring允许引入新的接口CQ何被通知的对象。例如,你可以用一个引入M对象实现 IsModified接口Q来化缓存?br>
  目标对象QTarget ObjectQ? 包含q接点的对象。也被称?被通知或被代理对象?br>
  AOP代理QAOP ProxyQ? AOP框架创徏的对象,包含通知?在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理?br>
  l入QWeavingQ? l装斚w来创Z个被通知对象。这可以在编译时 完成Q例如用AspectJ~译器)Q也可以在运行时完成。Spring和其他纯Java AOP框架一P 在运行时完成l入?br>
  Spring AOP 介绍

  Spring的一个关键组件就是AOP框架?Spring IoC容器(BeanFactory 和ApplicationContext)q不依赖于AOP, q意味着如果你不需要用,AOP可以不用QAOP完善了Spring IoCQ之成Z个有效的中间件解x案?br>
  Spring AOP 是Spring 框架的重要组成部分,它实CAOP联盟U定的接口。Spring AOP 是由UJava开发完成的。Spring AOP 只实CҎU别的连接点Q在J2EE应用中,AOP拦截到方法的操作已l够。OOP倡导的是Zsetter/getter 的方法访问,而非直接讉K域,而Spring 有够理׃仅提供方法的连接点。ؓ了控制反{QIoCQ很方便的用到非常健壮、灵zȝ企业服务Q则需要Spring AOP 的实现。Spring AOP 在运行时才创建Advice 对象。Spring AOP的优点如下:

  ·允许开发者用声明式企业服务Q比如事务服务、安全性服务?br>
  ·开发者可以开发满业务需求的自定义方面?br>
  ·开发Spring AOP Advice 很方便,可以借助代理cd速搭建Spring AOP 应用?br>
  使用Spring AOP松散耦合

  1、创建通知

  为实现AOPQ开发者需要开发AOP 通知(Advice)。AOP 通知QAdviceQ?包含了方面(AspectQ的逻辑。当创徏一个Advice 对象的时候,你就~写了实现横切(cross-cuttingQ功能?Spring 的连接点是用Ҏ拦截器实现的Q这意味着你编写的Spring AOP 通知在Ҏ调用的不同点l入q程序中。由于在调用一个方法时有几个不同的旉点,Spring 可以在不同的旉点组入进E序。Spring AOP中,提供了四U通知的接口: MethodBeforeAdvice 用于在目标方法调用前触发QAfterReturningAdvice 用于在目标方法调用后触发QThrowsAdvice 用于在目标方法抛出异常时触发QMethodInterceptor 用于实现 Around 通知QAdviceQ,在目Ҏ执行的前后触发?br>
  如果要实现相应功能,则需要实Cq对应的接口。例如:实现Before 通知QAdviceQ需要实现方?void before(Method method, Object[] args, Object target) Q实?After 通知QAdviceQ?需要实现方?void afterReturning (Method method, Object[] args, Object target)?

  2、在Spring 中定义切入点

  在不能明调用方法的时候,通知很不实用。切入点则可以决定特定的c,特定的方法是否匹配特定标准。如果某匚wQ则通知应用到此方法上。Spring 切入点允许用很灵zȝ方式通知l织q我们的cM。Spring 中的切入Ҏ架的核心是Pointcut接口Q此接口允许我们定义l入通知中的cdҎ。许多方面是通过一pd的通知和切入点l合来定义?br>
  在Spring中,一个advisor是一个方面的完整的模块化表示。Spring提供了PointcutAdvisor接口把通知和切入点l合成一个对象。Spring中很多内建的切入炚w有对应的PointcutAdvisorQ这使得你可以很方便在一个地方管理切入点和通知。Spring中的切入点分Zc:静态和动态。因为静态切入点的性能要优于动态切入点Q所以优先考虑使用。Spring 为我们提供创建静态切入点很实用的cStaticMethodMatherPointcut。在q个cMQ我们只需要关心setMappedName和setMappedNamsҎ。你可以使用具体的类名,也可以用通配W。如Q设|mappedName属性ؓset* 则匹配所有的setҎ。Springq提供了另通过正则表达式来创徏静态切入点的实用类RegexpMethodPointcut。通过使用Perl样式的正则表辑ּ来定义你感兴的Ҏ。当切入炚w要运行时参数值来执行通知Ӟq时需要用动态切入点。Spring提供了一个内建的动态切入点QControlFlowPointcutQ此切入点匹配基于当前线E的调用堆栈。我们可以在只有在当前线E执行的执行时找到特定的cd特定的方法才q回true。用动态切入点有很大的性能损耗。大多数的切入点可以静态确定,我们很少有机会创建动态切入点。ؓ了增加可切入点的可重用性,Spring 提供了切入点上的集合操作——交集和合ƈ?br>
  3、用ProxyFactoryBean创徏AOP代理

  ProxyFactoryBeanQ和其他Spring?FactoryBean实现一P引入一个间接的层次。如果你定义一个名字ؓmyfactory的ProxyFactoryBeanQ?引用myfactory的对象所看到的不是ProxyFactoryBean 实例本nQ而是由实现ProxyFactoryBean的类?getObject()Ҏ所创徏的对象。这个方法将创徏一个包装了目标对象 的AOP代理。用ProxyFactoryBean或者其他IoC可知的类来创建AOP代理的最重要的优点之一是IoC可以理通知和切入点。这是一个非常的强大的功能,能够实现其他AOP框架很难实现的特定的Ҏ。例如,一个通知本n可以引用应用对象Q除了目标对象, 它在MAOP框架中都可以引用应用对象Q,q完全得益于依赖注入所提供的可插入性。通常Q我们不需要ProxyFactoryBean的全部功能,因ؓ我们常常只对一个方面感兴趣Q?例如Q事务管理。当我们仅仅对一个特定的斚w感兴时Q我们可以用许多便利的工厂来创建AOP代理Q如QTransactionProxyFactoryBean?br>
  4、自动代?br>
  在应用较时Q只有很类需要被通知的时QProxyFactoryBean 可以很好的工作。当有许多类需要通知的时Q显C的创徏每个代理显得很J琐。幸q的是Spring提供了是使用自动通过容器来创Z理。这Ӟ只需要配|一个Bean来做J琐的工作。Spring提供了两个类实现自动代理QBeanNameAutoProxyCreator和DefaultAdvisorAutoProxyCreator。BeanNameAutoProxyCreator为匹配名字的Bean产生代理Q它可以使用在将一个或者多个方面应用在命名怼的Bean中。自动代理框架假设代理将要暴露出什么接口。如果目标Bean没有实现M接口Q这时就会动态生一个子cR而更强大的自动代理是DefaultAdvisorAutoProxyCreatorQ你所需要做的是在BeanFactory中包含它的配|。这个类的奇妙之处在于他使用实现了BeanPostProcessor接口。在Bean定义被加载倒Spring容器中后QDefaultAdvisorAutoProxyCreator搜索上下文中的AdvisorQ最后它Advisor应用到匹配Advisor切入点的Bean中。这个代理只对Advisor起作用,它需要通过Advisor来得到需要通知的Bean。元数据自动代理QMetaData AutoProxyQ。元数据自动代理配置依赖于源代码属性而不是外部XML配置文g。这可以非常方便的源代码和AOP元数据组l在同一个地斏V元数据自动代理最常用的地Ҏ用来声明事务。Spring提供了很强的框架来通过AOP框架来声明事务。这提供了在EJB使用声明式事务的相同功能?br>
  l论

  AOP 是面向对象编E的有力补充。通过斚w可以聚合在应用中行为Ş成可重用模块?br>
  通过E序可以实现怎样和在什么地Ҏ调用q些行ؓ。这可以减少代码重复Qƈ使你更加x业务逻辑。Spring 提供了AOP框架来实现调用方法时加入斚w。在AOP框架中可以很方便的用预定义的静态切入点来定义被调用的类和方法。我们需要通过Spring提供的代理类来生代理对象,可以使用ProxyFactoryBean也可以用自动代理。Spring AOP 的编E方式模块化了横向关注点的实玎ͼ提供了一个更好更快的软g开发方式。在软gl构日益扩大Q结构日益复杂的今天QSpring AOP 会发挥来重要的作用?


]]>
使用struts+spring+hibernatel装你的web应用架构 http://www.aygfsteel.com/hongyunxp/archive/2007/05/14/117207.html徐洪?/dc:creator>徐洪?/author>Sun, 13 May 2007 20:32:00 GMThttp://www.aygfsteel.com/hongyunxp/archive/2007/05/14/117207.htmlhttp://www.aygfsteel.com/hongyunxp/comments/117207.htmlhttp://www.aygfsteel.com/hongyunxp/archive/2007/05/14/117207.html#Feedback1http://www.aygfsteel.com/hongyunxp/comments/commentRss/117207.htmlhttp://www.aygfsteel.com/hongyunxp/services/trackbacks/117207.html使用struts+spring+hibernatel装你的web应用架构
      其实Q就用Java建造一个不是很烦琐的web应用Q也不是件轻杄事情?在构架的一开始就有很多事情要考虑?从高处看Q摆在开发者面前有很多问题Q要考虑是怎样建立用户接口Q在哪里处理业务逻辑Q?怎样持久化的数据?而这三层构架中,每一层都有他们要仔细考虑的?各个层该使用什么技术? 怎样的设计能松散耦合q能灉|改变Q?怎样替换某个层而不影响整体构架Q应用程序如何做各种U别的业务处理(比如事务处理Q?

      构架一个Web应用需要弄明白好多问题?q运的是Q已l有不少开发者已l遇到过q类问题Qƈ且徏立了处理q类问题的框架?一个好框架具备以下几点Q?减轻开发者处理复杂的问题的负担("不重复发明轮?Q; 内部有良好的扩展Q?q且有一个支持它的强大的用户团体?好的构架一般有针对性的处理某一c问题,q且能将它做好(Do One Thing wellQ?然而,你的E序中有几个层可能需要用特定的框架Q已l完成的UI(用户接口) q不代表你也可以把你的业务逻辑和持久逻辑偶合C的UI部分?举个例子Q?你不该在一个Controller(控制?里面写JDBC代码作ؓ你的业务逻辑Q?q不是控制器应该提供的?一个UI 控制器应该委z其它l在UI范围之外的轻量lg?好的框架应该能指g码如何分布?更重要的是,框架能把开发者从~码中解攑և来,使他们能专心于应用程序的逻辑Q这对客h说很重要Q?

      q篇文章讨论怎样l合几种著名的框架来使得你的应用E序做到村ּ耦合?
如何建立你的架构Qƈ且怎样让你的各个应用层保持一致。?如何整合框架以便让每个层在以一U松散偶合的方式彼此作用而不用管低层的技术细节?q对我们来说真是一U挑战?q里讨论一个整合框架的{略( 使用3 U受Ƣ迎的开源框? Q表C层我们用StrutsQ?业务层我们用SpringQ而持久层则用Hibernate?你也可以用其他FrameWork替换只要能得到同L效果?见图1 Q框架组合示意图Q?



应用E序的分?/span>

大部分的Web应用在职责上臛_能被分成4层?q四层是QpresentationQ描qͼQpersistenceQ持久)QbusinessQ业务)和domain modelQ域模块Q。每个层在处理程序上都应该有一Ҏ的责Q, 而不应该在功能上与其它层混合Qƈ且每个层要与其它层分开的,但要l他们之间放一个通信接口?我们׃介绍各个层开始,讨论一下这些层应该提供什么,不应该提供什么?



表示?The Presentation Layer)

一般来Ԍ一个典型的Web应用的的末端应该是表C层?很多Java发者也理解Struts所提供的?象业务逻辑之类的被打包到org.apache.struts.Action.Q?因此Q我们很赞成使用Strutsq样的框架?



下面是Struts所负责的:

* 理用户的请?做出相应的响应?

* 提供一个Controller ,委派调用业务逻辑和其它上层处理?

* 处理异常Q抛lStruts Action

* 为显C提供一个模?

* UI验证?



以下条款Q不该在Struts昄层的~码中经常出现?它们与显C层无关的?

* 直接的与数据库通信Q例如JDBC调用?

* 与你应用E序相关联的业务逻辑以及校验?

* 事物理?

在表C层引入q些代码Q则会带来高偶合和麻烦的l护?





持久?The Persistence Layer)

典型的Web应用的另一个末端是持久层。这里通常是程序最Ҏ失控的地斏V开发者L低估构徏他们自己的持久框架的挑战性。系l内部的持箋层不但需要大量调试时_而且q经常缺功能之变得难以控Ӟq是持久层的通病?q好有几个ORM开源框架很好的解决了这c问题。尤其是Hibernate?Hibernate为java提供了OR持久化机制和查询服务, 它还l已l熟悉SQL和JDBC API 的Java开发者一个学习桥梁,他们学习h很方ѝ?Hibernate的持久对象是ZPOJO和Java collections。此外,使用Hibernateq不妨碍你正在用的IDE?



L下面的条目,你在持久层编码中需要了解的?

* 查询对象的相关信息的语句?Hibernate通过一个OO查询语言QHQLQ或者正则表辄API来完成查询?HQL非常cM于SQL-- 只是把SQL里的table和columns用Object和它的fields代替?你需要学习一些新的HQL语言Q?不管怎样Q他们容易理解而文档也做的很好?HQL是一U对象查询的自然语言Q花很小的代价就能学习它?

* 如何存储Q更斎ͼ删除数据库记录?

* 象Hibernateq类的高UORM框架支持大部分主数据库Qƈ且他们支?Parent/child关系Q事物处理,l承和多态?



业务层(The Business LayerQ?/span>

一个典型Web应用的中间部分是业务层或者服务层?从编码的视角来看Q这层是最Ҏ被忽视的一层?而我们却往往在UI层或持久层周围看到这些业务处理的代码Q这其实是不正确的,因ؓ它导致了E序代码的紧密偶合,q样一来,随着旉推移q些代码很难l护。幸好,针对q一问题有好几种Frameworks存在?最受欢q的两个框架是Spring和PicoContainer?q些Z被称为microcontainersQ他们能让你很好的把对象搭配h?q两个框枉着手于‘依赖注射'(dependency injection)(q有我们知道?#8216;控制反{'Inversion of Control=IoC)q样的简单概c?q篇文章关注于Spring的注(译注Q通过一个给定参数的SetterҎ来构造Bean,有所不同于FactoryQ? Springq提供了Setter Injection(type2)QConstructor Injection(type3){方式供我们选择?Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction management handlerQ事物管理控Ӟ、Object Factoris(对象工厂)、service objectsQ服务组Ӟ——都通过XML来配|联pv来?



后面我们会D个例子来揭示一下Spring 是怎样q用q些概念?

业务层所负责的如下:

* 处理应用E序?业务逻辑和业务校?

* 理事物

* 允许与其它层怺作用的接?

* 理业务层别的对象的依赖?

* 在显C层和持久层之间增加了一个灵zȝ机制Q得他们不直接的联pd一赗?

* 通过揭示 从显C层C务层之间的Context来得到business services?

* 理E序的执行(从业务层到持久层Q?





域模块层QThe Domain Model Layer Q?/span>
既然我们致力于的是一个不是很复杂的Web的应用, 我们需要一个对象集合,让它在不同层之间Ud的?域模块层由实际需求中的业务对象组?比如, OrderLineItem , Product{等?开发者在q层 不用那些DTOsQ仅xdomain object卛_?例如QHibernate允许你将数据库中的信息存攑օ对象Qdomain objectsQ,q样你可以在q接断开的情况下把这些数据显C到UI层?而那些对象也可以q回l持l层Q从而在数据库里更新?而且Q你不必把对象{化成DTOsQ这可能似的它在不同层之间的在传输过E中丢失Q,q个模型使得Java开发者能很自然运用OOQ而不需要附加的~码?

一个简单例?



既然我们已经从全局上理解这些组件?现在p我们开始实践吧?我们q是?StrutsQSpring 和Hibernate。这三个框架已经被描q够多了Q这里就不重复介l了?q篇文章举例指导你如何用这三个框架整合开? q向你揭C?一个请求是如何贯穿于各个层的。(从用L加入一个Order到数据库Q显C;q而更新、删除)?



从这里可以下载到E序E序原代码(downloadQ?

既然每个层是互相作用的,我们先来创建domain objects。首先,我们要在q些Object中要定那些是需要持久化的,哪些是提供给business logicQ那些是昄接口的设计?下一步,我们配|我们的持久层ƈ且定义好Hibernate的OR mappings。然后定义好Business Objects。有了这些组成部分之后,我们?使用Spring把这些连接v来?最后,我们提供lSpring一个持久层Q从q个持久层里我们可以知道它是如何与业务逻辑层(business service layerQ通信的,以及它是怎样处理其他层抛出的异常的。?



域对象层QDomain Object LayerQ?/span>


q层是编码的着手点Q我们的~码׃q层开始?例子中Order 与OrderItem 是一个One—To—Many的关pR?下面是Domain Object Layer的两个对象:



· com.meagle.bo.Order.java: 包含了一个Order的概要信?

· com.meagle.bo.OrderLineItem.java: 包含了Order的详l信?

好好考虑怎你的package命名,q反应出了你是怎样分层的?例如 domain objects在程序中可能打包在com.meagle.bo内?更详l一点将打包在com. meagle.bo的子目录下面。business logic应该从com.meagle.serice开始打包,而DAO 对象应该位于com.meagle.service.dao.hibernate。反应Forms和Actions?持久对象Qpresentation classesQ?应该分别攑֜ com.meagle.action和com.meagle.forms包?准确的给包命名得你的classes很好分割q且易于l护Qƈ且在你添加新的classesӞ能得程序结构上保持上下一致?

持久层的配置QPersistence Layer ConfigurationQ?/span>

建立Hibernate的持久层 需要好几个步骤?W一步让我们把BO持久化?既然Hibernate是通过POJO工作的, 因此Order?OrderLineItem对象需要给所有的fileds 加上getter,setterҎ?Hibernate通过XML文g来映?OR)对象Q以下两个xml文g分别映射了Order 和OrderItem对象。(q里有个叫XDoclet工具可以自动生成你的XML影射文gQ?

- Order.hbm.xml
- OrderLineItem.hbm.xml

你可以在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文g。Hibernate?[urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用来告诉程?应该与哪个数据库通信Q该使用哪个q接池或使用了DataSourceQ?应该加蝲哪些持久对象。?a target=_blank rel=nofollow>Session接口是用来完成SelectingQSavingQDelete和Updatingq些操作?后面的我们将讲述SessionFactory和Session是怎样讄的?

业务层的配置QBusiness Layer ConfigurationQ?/span>

既然我们已经有了domain objectsQ接下来我们pbusiness service objects了,用他们来执行E序的logic,调用持久层,得到UI层的requests,处理transactionsQƈ且控制exceptions?Z这些连接v来ƈ且易于管理,我们用面向方面的 SpringFramework?Spring 提供?控制倒置Qinversion of control 0==IoC)和注依赖设|(setter dependency injectionQ这些方式(可供选择Q,用XML文g对象连接v来?IoC是一个简单概念(它允怸个对象在上层接受其他对象的创建)Q用IoCq种方式让你的对象从创徏中释放了出来Q降低了偶合度?




q里是一个没有用IoC的对象创建的例子Q它有很高偶合度?




?2.没有使用 IoC. A 创徏?B ?C

而这里是一个用IoC的例子,q种方式允许对象在高层可以创建ƈq入另外一个对象,所以这样可以直接被执行?


?3. 对象使用?IoC?A 包含了接受B,C?setterҎ , q同栯C 由A创徏B,C的目的?/span>

建立我们的业务服务对象(Building Our Business Service ObjectsQ?


Business Object中的SetterҎ接受的是接口Q这h们可以很松散的定义对象实玎ͼ然后注入?在我们的案例中,我们用一个business service object接收一个DAO,用它来控制domain objects的持久化?׃在这个例子中使用了HibernateQ我们可以很方便的用其他持久框架实现 同时通知Spring 有新的DAO可以使用了?

在面向接口的~程中,你会明白 "注射依赖"模式是怎样松散耦合你的业务逻辑和持久机制的Q)?



下面是一个接口business service objectQDAO代码片段Q?


代码:

public interface IOrderService {

  public abstract Order saveNewOrder(Order order)

    throws OrderException,

           OrderMinimumAmountException;

 

  public abstract List findOrderByUser(

                                     String user)

                           throws OrderException;

 

  public abstract Order findOrderById(int id)

                           throws OrderException;

 

  public abstract void setOrderDAO(

                             IOrderDAO orderDAO);

}

 

注意到这D代码里有一?setOrderDaoQ)Q它是一个DAO Object讄ҎQ注器Q?但这里ƈ没有一个getOrderDao的方法,q不必要Q因Zq不会在外部讉Kq个orderDao。这个DAO Objecte被调用Q和我们的persistence layer 通信。我们将用Spring把DAO Object ?business service object搭配h的。因为我们是面向接口~程的,所以ƈ不需要将实现cȝ密的耦合在一赗?



接下L们开始我们的DAO的实现类q行~码?既然Spring已经有对Hibernate的支持,那这个例子就直接l承HibernateDaoSupportcMQ这个类很有用,我们可以参?a target=_blank rel=nofollow>HibernateTemplateQ它主要是针对HibernateDaoSupport的一个用法,译注Q具体可以查?a target=_blank rel=nofollow>Srping 的APIQ?下面是这个DAO接口代码Q?

代码:
public interface IOrderDAO {
  public abstract Order findOrderById(
                                    final int id);
 
  public abstract List findOrdersPlaceByUser(
                           final String placedBy);
  public abstract Order saveOrder(
                               final Order order);
}


我们仍然要给我们持久层组装很多关联的对象Q这里包含了HibernateSessionFactory 和TransactionManager?Spring 提供了一?HibernateTransactionManagerQ他用线E捆l了一个Hibernate SessionQ用它来支持transactions(h?a target=_blank rel=nofollow>ThreadLocal) ?

下面是HibernateSessionFactory ?HibernateTransactionManager:的配|:

代码:
<bean id="mySessionFactory"
       class="org.springframework.orm.hibernate.
              LocalSessionFactoryBean">
  <property name="mappingResources">
    <list>
      <value>
        com/meagle/bo/Order.hbm.xml
      </value>
      <value>
        com/meagle/bo/OrderLineItem.hbm.xml
      </value>
    </list>
  </property>
  <property name="hibernateProperties">
    <props>
      <prop key="hibernate.dialect">
        net.sf.hibernate.dialect.MySQLDialect
      </prop>
      <prop key="hibernate.show_sql">
        false
      </prop>
      <prop key="hibernate.proxool.xml">
        C:/MyWebApps/.../WEB-INF/proxool.xml
      </prop>
      <prop key="hibernate.proxool.pool_alias">
          spring
      </prop>
    </props>
  </property>
</bean>
 
<!-- Transaction manager for a single Hibernate
SessionFactory (alternative to JTA) -->
<bean id="myTransactionManager"
         class="org.
                springframework.
                orm.
                hibernate.
                HibernateTransactionManager">
  <property name="sessionFactory">
    <ref local="mySessionFactory"/>
  </property>
  </bean>



可以看出Q每个对象都可以在Spring 配置信息中用<bean>标签引用。在q里QmySessionFactory引用了HibernateSessionFactoryQ而myTransactionManager引用了HibernateTransactionManage?注意代码中myTransactionManger Bean有个sessionFactory属性?HibernateTransactionManager有个sessionFactory setter ?getterҎQ这是用来在Spring启动的时候实?依赖注入" Qdependency injectionQ的?在sessionFactory 属性里 引用mySessionFactory。这两个对象在Spring容器初始化后pl装了v来了?q样的搭配让你从 单例Qsingleton objectsQ和工厂QfactoriesQ中解放了出来,降低了代码的l护代h?mySessionFactory.的两个属性,分别是用来注入mappingResources ?hibernatePropertes的。通常Q如果你在Spring之外使用Hibernate,q样的设|应该放在hibernate.cfg.xml中的?不管怎样,Spring提供了一个便L方式-----在Spring内部配置中ƈ入了Hibernate的配|?如果要得到更多的信息Q可以查阅Spring API?





既然我们已经l装配置好了Service BeansQ就需要把Business Service Object?DAO也组装v来,q把q些对象配到一个事务管理器Qtransaction managerQ里?



在Spring中的配置信息Q?
代码:

<!-- ORDER SERVICE -->
<bean id="orderService"
  class="org.
         springframework.
         transaction.
         interceptor.
         TransactionProxyFactoryBean">
  <property name="transactionManager">
    <ref local="myTransactionManager"/>
  </property>
  <property name="target">
    <ref local="orderTarget"/>
  </property>
  <property name="transactionAttributes">
    <props>
      <prop key="find*">
     PROPAGATION_REQUIRED,readOnly,-OrderException
      </prop>
      <prop key="save*">
     PROPAGATION_REQUIRED,-OrderException
      </prop>
    </props>
  </property>
</bean>
 
<!-- ORDER TARGET PRIMARY BUSINESS OBJECT:
Hibernate implementation -->
<bean id="orderTarget"
         class="com.
                meagle.
                service.
                spring.
                OrderServiceSpringImpl">
  <property name="orderDAO">
    <ref local="orderDAO"/>
  </property>
</bean>
 
<!-- ORDER DAO OBJECT -->
<bean id="orderDAO"
         class="com.
                meagle.
                service.
                dao.
                hibernate.
                OrderHibernateDAO">
  <property name="sessionFactory">
    <ref local="mySessionFactory"/>
  </property>
</bean>




? 是我们对象搭建的一个提UӀ?从中可以看出Q每个对象都联系着SpringQƈ且能通过Spring注入到其他对象。把它与Spring的配|文件比较,观察他们之间的关p?



?4. Spring是q样Z配置文gQ将各个Bean搭徏在一赗?/span>

q个例子使用一个TransactionProxyFactoryBeanQ它定义了一个setTransactionManager()?q对象很有用Q他能很方便的处理你x的事物还有Service Object?你可以通过transactionAttributes属性来定义怎样处理?想知道更多还是参考TransactionAttributeEditor吧?

TransactionProxyFactoryBean q有个setter. q会被我?Business service objectQorderTargetQ引用, orderTarget定义?业务服务层,q且它还有个属性,由setOrderDAO()引用。这个属?



Spring 和Bean 的还有一点要注意的: bean可以以用两种方式创造?q些都在单例模式QSingtonQ和原型模式QpropotypeQ中定义了?默认的方式是singleton,q意味着׃n的实例将被束~?而原形模式是在Spring用到bean的时候允许新建实例的。当每个用户需要得C们自己Bean的CopyӞ你应该仅使用prototype模式。(更多的请参考设计模式中的单例模式和原Ş模式Q?

提供一个服务定位器QProviding a Service LocatorQ?/span>
既然我们已经我们的Serices和DAO搭配h了。我们需要把我们的Service昄到其他层?q个通常是在Struts或者Swingq层里编码。一个简单方法就是用 服务定位器返回给Spring context 。当Ӟ可以通过直接调用Spring中的Bean来做?

下面是一个Struts Actin 中的服务定位器的一个例子?
代码:

public abstract class BaseAction extends Action {
 
  private IOrderService orderService;
 
  public void setServlet(ActionServlet
                                 actionServlet) {
    super.setServlet(actionServlet);
    ServletContext servletContext =
               actionServlet.getServletContext();
 
    WebApplicationContext wac =
      WebApplicationContextUtils.
         getRequiredWebApplicationContext(
                                 servletContext);
 
      this.orderService = (IOrderService)
                     wac.getBean("orderService");
  }
 
  protected IOrderService getOrderService() {
    return orderService;
  }
}
 

UI 层配|?QUI Layer ConfigurationQ?/span>

q个例子里UI?使用了Struts framework. q里我们要讲qC下在l程序分层的时候, 哪些是和Struts部分的。我们就从一个Struts-config.xml文g中的Action的配|信息开始吧?
代码:

struts-config.xml file.

<action path="/SaveNewOrder"
    type="com.meagle.action.SaveOrderAction"
    name="OrderForm"
    scope="request"
    validate="true"
    input="/NewOrder.jsp">
  <display-name>Save New Order</display-name>
  <exception key="error.order.save"
    path="/NewOrder.jsp"
    scope="request"
    type="com.meagle.exception.OrderException"/>
  <exception key="error.order.not.enough.money"
    path="/NewOrder.jsp"
    scope="request"
    type="com.
          meagle.
          exception.
          OrderMinimumAmountException"/>
  <forward name="success" path="/ViewOrder.jsp"/>
  <forward name="failure" path="/NewOrder.jsp"/>
</action>

SaveNewOrder q个Action是用来持久化UI层里的表单提交过来Order的。这是Struts中一个很典型的Action; 注意观察q个Action中exception配置Q这些Exceptions也在Spring 配置文g(applicationContext-hibernate.xml)中配|了Q就?business service object 的transactionAttributes属性里Q?当异常在业务层被被抛出时Q我们可以控制他们,q当的显C给UI层?

W一个异常,OrderException,在持久层保存order对象p|的时候被触发。这导致事物回滚ƈ且通过BO把异常回传到Strutsq一层?

W二个异常,OrderMinimumAmountException也同W一个一栗?





搭配整和的最后一?通过是让你显C层和业务层相结合。这个已l被服务定位器(service locatorQ实CQ前面讨了)Q?q里服务层作Z个接口提供给我们的业务逻辑和持久层?



SaveNewOrder Action 在Struts中用一个服务定位器Qservice locatorQ来调用执行业务Ҏ的?Ҏ代码如下Q?



代码:
public ActionForward execute(

  ActionMapping mapping,

  ActionForm form,

  javax.servlet.http.HttpServletRequest request,

  javax.servlet.http.HttpServletResponse response)

  throws java.lang.Exception {

 

  OrderForm oForm = (OrderForm) form;

 

  // Use the form to build an Order object that

  // can be saved in the persistence layer.

  // See the full source code in the sample app.

 

  // Obtain the wired business service object

  // from the service locator configuration

  // in BaseAction.

  // Delegate the save to the service layer and

  // further upstream to save the Order object.

  getOrderService().saveNewOrder(order);

 

  oForm.setOrder(order);

 

  ActionMessages messages = new ActionMessages();

  messages.add(

      ActionMessages.GLOBAL_MESSAGE,

            new ActionMessage(

      "message.order.saved.successfully"));

 

  saveMessages(request, messages);

 

  return mapping.findForward("success");

}


ȝ

q篇文章在技术和构架斚w掩盖了很多低层的基础信息Q?文章的主要的意图在于让你意识到如何给你应用程序分层?分层可以"解?你的代码——允许新的组件被dq来Q而且让你的代码易于维护?q里用到的技术只是专注于?解偶"做好?不管怎样Q用这L构架可以让你用其他技术代替现在的层?例如Q你可能不用Hibernate实现持久化。既然你在DAO中面向接口的~程的,所以你完全可以用iBATIS来代ѝ或者,你也可能想用Struts外的其他的技术或者框架替换现在的UI层(转换久层Q实现层q不应该直接影响C的业务逻辑和业务服务层Q?用适当的框架搭Z的Web应用Q其实也不是一件烦琐的工作Q更主要的是?解?了你E序中的各个层?





后记Q?

看完q篇文章后,只是觉得很喜Ƣ,于是q译了Q当然同时也准备着挨大家扔来的鸡蛋Q)?

q篇文章里ƈ没有太多的技术细节,和详l的步骤。如果你从未使用q这些框架而在q行实例E序遇上困难的话Q可以到CSDN论坛Java Open Source版发_我一定会详细解答的(啊哦Q这不算做广告吧Q)Q?

文章是从一个构架的角度讲述了如何搭配现有的开源框架进行分层, 有太多的术语我都不知道怎么表达Q而且可能有很多语句存在错误。如果媄响了你的阅读Q请你直接点原文地址Q我同时也象你说声抱歉?



作者简介:Mark Eagle 高软g工程师,亚特兰大?
?译:Totodo,软g工程?





参考:

StrutsQhttp://jakarta.apache.org/struts/index.html

Spring: http://www.springframework.org

Hibernate: http://www.hibernate.org

http://www.hibernate.org.cn

关于控制反{IOC和依赖注:http://www.martinfowler.com/articles/injection.html

原文:

http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=1
http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=2
http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=3
http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=4


]]>
վ֩ģ壺 | | ͨ| ϴ| | | | ѽ| ף| ̨| | | | | | | | ƽ| ˼| ׶| ɽ| ɽ| Ҫ| | | | ˮ| ư| ָ| ̶| Դ| ״| ͼʲ| ڳ| Զ| Դ| | | | | |