




免费预览已结束,剩余27页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
AOP(Aspect Oriented Programming),也就是面向方面编程的技术。AOP基于IoC基础,是对OOP的有益补充。AOP将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面Crosscutting enterprise concerns,例如,所有大中型应用都要涉及到的持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging)等。AOP正在成为软件开发的下一个光环。使用AOP,你可以将处理aspect的代码注入主程序,通常主程序的主要目的并不在于处理这些aspect。AOP可以防止代码混乱。Spring framework是很有前途的AOP技术。作为一种非侵略性的、轻型的AOP framework,你无需使用预编译器或其他的元标签,便可以在Java程序中使用它。这意味着开发团队里只需一人要对付AOP framework,其他人还是像往常一样编程。AOP概念让我们从定义一些重要的AOP概念开始。 方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现。 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。 通知(Advice):在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。 切入点(Pointcut):指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。 引入(Introduction):添加方法或字段到被通知的类。Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。 目标对象(Target Object):包含连接点的对象,也被称作被通知或被代理对象。 AOP代理(AOP Proxy):AOP框架创建的对象,包含通知。在Spring中,AOP代理可以是JDK动态代理或CGLIB代理。 编织(Weaving):组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。各种通知类型包括: Around通知:包围一个连接点的通知,如方法调用。这是最强大的通知。Aroud通知在方法调用前后完成自定义的行为,它们负责选择继续执行连接点或通过返回它们自己的返回值或抛出异常来短路执行。 Before通知:在一个连接点之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。 Throws通知:在方法抛出异常时执行的通知。Spring提供强制类型的Throws通知,因此你可以书写代码捕获感兴趣的异常(和它的子类),不需要从Throwable或Exception强制类型转换。 After returning通知:在连接点正常完成后执行的通知,例如,一个方法正常返回,没有抛出异常。Around通知是最通用的通知类型。大部分基于拦截的AOP框架(如Nanning和Jboss 4)只提供Around通知。如同AspectJ,Spring提供所有类型的通知,我们推荐你使用最为合适的通知类型来实现需要的行为。例如,如果只是需要用一个方法的返回值来更新缓存,你最好实现一个after returning通知,而不是around通知,虽然around通知也能完成同样的事情。使用最合适的通知类型使编程模型变得简单,并能减少潜在错误。例如,你不需要调用在around通知中所需使用的MethodInvocation的proceed()方法,因此就调用失败。切入点的概念是AOP的关键,它使AOP区别于其他使用拦截的技术。切入点使通知独立于OO的层次选定目标。例如,提供声明式事务管理的around通知可以被应用到跨越多个对象的一组方法上。 因此切入点构成了AOP的结构要素。 拦截器(也称拦截机) 拦截机 (Interceptor), 是 AOP (Aspect-Oriented Programming) 的另一种叫法。AOP本身是一门语言,只不过我们使用的是基于JAVA的集成到Spring 中的 SpringAOP。同样,我们将通过我们的例子来理解陌生的概念。 接口类Java代码 1 package com.test.TestSpring3; 2 3 public interface UserService / 被拦截的接口 4 . 5 public void printUser(String user); 6 7 实现类Java代码 8 package com.test.TestSpring3; 9 10 public class UserServiceImp implements UserService / 实现UserService接口 11 . 12 public void printUser(String user) . 13 System.out.println(printUser user: + user);/ 显示user 14 15 16 17 AOP拦截器Java代码 18 package com.test.TestSpring3; 19 20 import ercept.MethodInterceptor; 21 import ercept.MethodInvocation; 22 23 public class UserInterceptor implements MethodInterceptor 24 / AOP方法拦截器 25 . 26 27 public Object invoke(MethodInvocation arg0) throws Throwable . 28 29 try . 30 31 if (arg0.getMethod().getName().equals(printUser) 32 / 拦截方法是否是UserService接口的printUser方法 33 . 34 Object args = arg0.getArguments();/ 被拦截的参数 35 System.out.println(user: + args0); 36 arg0.getArguments()0 = hello!;/ 修改被拦截的参数 37 38 39 40 System.out.println(arg0.getMethod().getName() + -!); 41 return ceed();/ 运行UserService接口的printUser方法 42 43 catch (Exception e) . 44 throw e; 45 46 47 48 49 测试类Java代码 50 package com.test.TestSpring3; 51 52 import org.springframework.beans.factory.BeanFactory; 53 54 import org.springframework.beans.factory.xml.XmlBeanFactory; 55 import org.springframework.context.ApplicationContext; 56 import org.springframework.context.support.ClassPathXmlApplicationContext; 57 import org.springframework.context.support.FileSystemXmlApplicationContext; 58 import org.springframework.core.io.ClassPathResource; 59 import org.springframework.core.io.Resource; 60 import org.springframework.web.context.support.WebApplicationContextUtils; 61 62 public class TestInterceptor . 63 64 public static void main(String args) . 65 ApplicationContext ctx = new FileSystemXmlApplicationContext( 66 classpath:applicationContext.xml); 67 / ApplicationContext ctx = new ClassPathXmlApplicationContext(applicationContext.xml); 68 69 UserService us = (UserService) ctx.getBean(userService); 70 us.printUser(shawn); 71 72 73 74 配置文件 Xml代码 75 76 77 78 80 81 82 83 85 86 87 com.test.TestSpring3.UserService 88 89 90 91 92 93 94 95 96 userInterceptor 97 98 99 100 101 102 输出: user:shawn printUser-! printUser user:hello! 结论:调用方法的时候 传入的值被拦截修改了.拦截器中的事务管理(事务拦截机) 如果不采用拦截机的机制时,在使用JDBC进行数据库访问时,存在两种情况: 自动提交 这是JDBC驱动默认的模式,每次数据库操作(CRUD)成功完成后,都作为一个单独的事务自动提交,如果未成功完成,即抛出了 SQLException 的话,仅最近的一个操作将回滚。非自动提交 这是想更好的控制事务时需要程序地方式进行控制:o 在进行该事务单元的任何操作之前 setAutoCommit(false)o 在成功完成事务单元后 commit()o 在异常发生后 rollback()自动提交模式是不被推荐的,因为每个操作都将产生一个事务点,这对于大的应用来说性能将受到影响;再有,对于常见的业务逻辑,这种模式显得无能为力。比如:转帐,从A帐户取出100元,将其存入B帐户;如果在这两个操作之间发生了错误,那么用户A将损失了100元,而本来应该给帐户B的,却因为失败给了银行。所以,建议在所有的应用中,如果使用 JDBC 都将不得不采用非自动提交模式(你们要能发现了在我们的 JDBC 那个例子中,我们采用的就是自动提交模式,我们是为了把精力放在JDBC上,而不是事务处理上),即我们不得不在每个方法中:Java代码 103 try 104 / 在获得连接后,立即通过调用setAutoCommit(false) 将事务处理置为非自动提交模式 / Prepare Query to fetch the user Information 105 pst = conn.prepareStatement(findByName); 106 / . mit(); 107 catch(Exception ex) 108 conn.rollback(); 109 throw ex; 110 finally 111 try 112 / Close Result Set and Statement 113 if (rset != null) rset.close(); 114 if (pst != null) pst.close(); 115 catch (Exception ex) 116 ex.printStackTrace(); 117 throw new Exception(SQL Error while closing objects = + ex.toString(); 118 119 120 这样代码在AOP的倡导者看来是“肮脏”的代码。他们认为,所有的与事务有关的方法都应当可以集中配置(见声明性事务控制),并自动拦截,程序应当关心他们的主要任务,即商业逻辑,而不应和事务处理的代码搅和在一起。我先看看 Spring 是怎么做到拦截的:Spring 内置支持的事务处理拦截机这里因为要用到JpetStore项目中的代码,我们将 applicationContext.xml 全部内容列出: WEB-INF/perties WEB-INF/perties 这个配置比想象的要简单的多:Xml代码 121 122 126 127 128 129 1. 所有的拦截机配置都放在 配置元素中.2. 下面还是需要理解一下几个有关AOP的专用名词,不过,是挺抽象的,最好能会意出其的用意 pointcut 切入点,比如:updateAccount 方法需要进行事务管理,则这个切入点就是“执行方法体”(execution)。Spring 所有支持的切入点类型在都在 Spring reference: . Supported Pointcut Designators 中列出了。 advice 要对这个切入点进行什么操作,比如事务控制 advisor Spring 特有的概念,将上两个概念合到一个概念中来,即一个 advisor 包含了一个切入点及对这个切入点所实施的操作。因为 方法执行切入点 execution 为最常见的切入点类型,我们着重介绍一下,execution 的完全形式为:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)这是一个正则表达式,其中由 ? 结尾的部分是可选的。翻译过来就是:执行(方法访问修饰符? 方法返回类型 声明类型? 方法名(方法参数类型) 抛出异常?)所有的这些都是用来定义执行切入点,即那些方法应该被侯选为切入点: 方法访问修饰符 即 public, private 等等 方法返回类型 即方法返回的类型,如 void, String 等等 声明类型 1.5的语法,现在可以先忽略它 方法名 方法的名字 方法参数类型 方法的参数类型 抛出异常 方法声明的抛出的异常例如,所有dao代码被定义在包 com.xyz.dao及子包 com.xyz.dao.hibernate, 或者其它,如果还有的话,子包中, 里面定义的是提供DAO功能的接口或类,那么表达式:execution(* com.xyz.dao.*.*(.)表示切入点为:执行定义在包 com.xyz.dao 及其子包(因为 . 所致) 中的任何方法详细情况可以参见 Spring refernce: . Examples因此这个表达式为执行定义在类 PetStoreFacade及其实现类中的所有方法,采取的动作定义在 txAdvice 中. 关于该 advice 的定义,(见声明性事务控制)一节 Spring 自定拦截机来为了进行事务控制,我们只需简单地配置几下,所有的工作都由 Spring 来做。这样固然很好,但有时我们需要有我们特有的控制逻辑。因为Spring 不可能包含所有人需要的所有拦截机。所以它提供了通过程序的方式加以定制的方式。我们的项目中就有这么一个拦截机,在用户确认付款后,将定单信息通过 email 的方式发送给注册用户的邮箱中。 . 红色的注释已经说的很清楚这个 Advisor 了,它的切入点(pointcut) 为 PetStoreFacade 的 void insertOrder(Order order) 方法,采取的动作为引用的 emailAdvice, 下面我们就来看看 emailAdvice: 它给了这个 advice 的实现类为 logic 包中 SendOrderConfirmationEmailAdvice, 该Bean 引用了我们前面定义的邮件发送器(一个 Spring 内置的邮件发送器).下面看看这个实现类:public class SendOrderConfirmationEmailAdvice implements AfterReturningAdvice, InitializingBean / user jes on localhost private static final String DEFAULT_MAIL_FROM = ; private static final String DEFAULT_SUBJECT = Thank you for your order!; private final Log logger = LogFactory.getLog(getClass(); private MailSender mailSender; private String mailFrom = DEFAULT_MAIL_FROM; private String subject = DEFAULT_SUBJECT; public void setMailSender(MailSender mailSender) this.mailSender = mailSender; public void setMailFrom(String mailFrom) this.mailFrom = mailFrom; public void setSubject(String subject) this.subject = subject; public void throws Exception if (this.mailSender = null) throw new IllegalStateException(mailSender is required); /* * * param returnValue 被拦截的方法的返回值 * param m 被拦截的方法的所有信息(Method类封装了这些信息) * param args 被拦截的方法的所有参数组成的数组 * param target 目标对象,对于方法执行来说,即是方法所在的类的实例(与 this 同,批当前对象) * throws java.lang.Throwable */ public void afterReturning(Object returnValue, Method m, Object args, Object target) throws Throwable / 我们被拦截的方法为 void insertOrder(Order order),方法只有一个参数,所以可知数据的第1个元素即是被传进的order 对象 / 得到了order 对象,就可以将 order 对应的帐户名及帐单号发送到邮件中,以便确认无误。 Order order = (Order) args0; Account account = (PetStoreFacade) target).getAccount(order.getUser().getUsername(); / dont do anything if email address is not set if (account.getEmail() = null | account.getEmail().length() = 0) return; StringBuffer text = new StringBuffer(); text.append(Dear ).append(account.getFirstname(). append( ).append(account.getLastname(); text.append(, thank your for your order from JPetStore. + Please note that your order number is ); text.append(order.getId(); SimpleMailMessage mailMessage = new SimpleMailMessage(); mailMessage.setTo(account.getEmail(); mailMe
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025版外汇市场交易手续费支付合同
- 2025年度航空航天材料采购合同规范范本
- 2025年度企业环保审批代办服务合同
- 2025版配餐服务食品安全责任协议书版范本
- 2025版历史文化遗址保护与修复居间服务协议
- 2025版挖掘机租赁项目安全生产责任书
- 2025版新能源充电桩售后服务及保障合同
- 2025版水利工程土方施工合同
- 2025年公积金贷款二手房买卖合同及合同解除条件条款
- 2025年度高端会所室内涂料施工服务协议
- 物理化学实验:实验一 溶解热的测定
- 茂县生活垃圾资源化综合利用项目环评报告
- 4月份公路养护工作计划
- 保安员在岗培训法律-2
- 初中英语中考专题训练阅读理解-应用文篇
- YC/T 210.2-2006烟叶代码第2部分:烟叶形态代码
- GB/T 20671.1-2006非金属垫片材料分类体系及试验方法第1部分:非金属垫片材料分类体系
- 熵权法教学讲解课件
- 医师病理知识定期考核试题与答案
- 课堂因“融错·容错·溶措”而精彩
- 安宁疗护服务流程
评论
0/150
提交评论