1、一个简单的Spring MVC例子AOP(Aspect Oriented Programming),也就是面向方面编程的技术。AOP基于IoC基础,是对OOP的有益补充。AOP将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面Crosscutting enterprise concerns,例如,所有大中型应用都要涉及到的持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging)等。AOP正在成为软件开发的
2、下一个光环。使用AOP,你可以将处理aspect的代码注入主程序,通常主程序的主要目的并不在于处理这些aspect。AOP可以防止代码混乱。Spring framework是很有前途的AOP技术。作为一种非侵略性的、轻型的AOP framework,你无需使用预编译器或其他的元标签,便可以在Java程序中使用它。这意味着开发团队里只需一人要对付AOP framework,其他人还是像往常一样编程。AOP概念让我们从定义一些重要的AOP概念开始。 方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的A
3、dvisor或拦截器实现。 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。 通知(Advice):在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。 切入点(Pointcut):指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点,例如,使用正则表达式。 引入(Introduction):添加方法或字段到被通知的类。Spring允许引入新的接口到任何被通知的对
4、象。例如,你可以使用一个引入使任何对象实现IsModified接口,来简化缓存。 目标对象(Target Object):包含连接点的对象,也被称作被通知或被代理对象。 AOP代理(AOP Proxy):AOP框架创建的对象,包含通知。在Spring中,AOP代理可以是JDK动态代理或CGLIB代理。 编织(Weaving):组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。各种通知类型包括: Around通知:包围一个连接点的通知,如方法调用。这是最强大的通知。Aroud通知在
5、方法调用前后完成自定义的行为,它们负责选择继续执行连接点或通过返回它们自己的返回值或抛出异常来短路执行。 Before通知:在一个连接点之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。 Throws通知:在方法抛出异常时执行的通知。Spring提供强制类型的Throws通知,因此你可以书写代码捕获感兴趣的异常(和它的子类),不需要从Throwable或Exception强制类型转换。 After returning通知:在连接点正常完成后执行的通知,例如,一个方法正常返回,没有抛出异常。Around通知是最通用的通知类型。大部分基于拦截的AOP框架(如Nanning和J
6、boss 4)只提供Around通知。如同AspectJ,Spring提供所有类型的通知,我们推荐你使用最为合适的通知类型来实现需要的行为。例如,如果只是需要用一个方法的返回值来更新缓存,你最好实现一个after returning通知,而不是around通知,虽然around通知也能完成同样的事情。使用最合适的通知类型使编程模型变得简单,并能减少潜在错误。例如,你不需要调用在around通知中所需使用的MethodInvocation的proceed()方法,因此就调用失败。切入点的概念是AOP的关键,它使AOP区别于其他使用拦截的技术。切入点使通知独立于OO的层次选定目标。例如,提供声明式
7、事务管理的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 p
8、rintUser(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;
9、 19 20 import org.aopalliance.intercept.MethodInterceptor; 21 import org.aopalliance.intercept.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.getMetho
10、d().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 arg0.proceed();/ 运行Use
11、rService接口的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.ApplicationCon
12、text; 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.we
13、b.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(appl
14、icationContext.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 us
15、er:hello! 结论:调用方法的时候 传入的值被拦截修改了.拦截器中的事务管理(事务拦截机) 如果不采用拦截机的机制时,在使用JDBC进行数据库访问时,存在两种情况: 自动提交 这是JDBC驱动默认的模式,每次数据库操作(CRUD)成功完成后,都作为一个单独的事务自动提交,如果未成功完成,即抛出了 SQLException 的话,仅最近的一个操作将回滚。非自动提交 这是想更好的控制事务时需要程序地方式进行控制:o 在进行该事务单元的任何操作之前 setAutoCommit(false)o 在成功完成事务单元后 commit()o 在异常发生后 rollback()自动提交模式是不被推荐的,
16、因为每个操作都将产生一个事务点,这对于大的应用来说性能将受到影响;再有,对于常见的业务逻辑,这种模式显得无能为力。比如:转帐,从A帐户取出100元,将其存入B帐户;如果在这两个操作之间发生了错误,那么用户A将损失了100元,而本来应该给帐户B的,却因为失败给了银行。所以,建议在所有的应用中,如果使用 JDBC 都将不得不采用非自动提交模式(你们要能发现了在我们的 JDBC 那个例子中,我们采用的就是自动提交模式,我们是为了把精力放在JDBC上,而不是事务处理上),即我们不得不在每个方法中:Java代码 103 try 104 / 在获得连接后,立即通过调用setAutoCommit(false
17、) 将事务处理置为非自动提交模式 / 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.
18、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/mail.properties WEB-INF/jdbc.properties !- =
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1