Spring AOP原理及拦截器(aop配置最简单,利用环绕也能实现)

AOP除了实现自身的拦截器外,还可以用环绕通知aop,实现拦截的啊,如果参数不符合要求,则不会让它跳转到下一个进程中

原理

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-OrientedProgramming) 的另一种叫法。AOP本身是一门语言,只不过我们使用的是基于JAVA的集成到Spring 中的 SpringAOP。同样,我们将通过我们的例子来理解陌生的概念。

   接口类

Java代码
  1. package com.test.TestSpring3;   
  2.   
  3. public interface UserService // 被拦截的接口  
  4. ...{   
  5.     public void printUser(String user);   
  6. }   

 实现类

Java代码
  1. package com.test.TestSpring3;   
  2.   
  3. public class UserServiceImp implements UserService // 实现UserService接口  
  4. ...{   
  5.     public void printUser(String user) ...{   
  6.         System.out.println("printUser user:" + user);// 显示user  
  7.     }   
  8. }   
  9.   

 AOP拦截器

Java代码
  1. package com.test.TestSpring3;   
  2.   
  3. import org.aopalliance.intercept.MethodInterceptor;   
  4. import org.aopalliance.intercept.MethodInvocation;   
  5.   
  6. public class UserInterceptor implements MethodInterceptor   
  7. // AOP方法拦截器   
  8. ...{   
  9.   
  10.     public Object invoke(MethodInvocation arg0) throws Throwable ...{   
  11.   
  12.         try ...{   
  13.   
  14.             if (arg0.getMethod().getName().equals("printUser"))   
  15.             // 拦截方法是否是UserService接口的printUser方法  
  16.             ...{   
  17.                 Object[] args = arg0.getArguments();// 被拦截的参数  
  18.                 System.out.println("user:" + args[0]);   
  19.                 arg0.getArguments()[0] = "hello!";// 修改被拦截的参数  
  20.   
  21.             }   
  22.   
  23.             System.out.println(arg0.getMethod().getName() + "---!");   
  24.             return arg0.proceed();// 运行UserService接口的printUser方法  
  25.   
  26.         } catch (Exception e) ...{   
  27.             throw e;   
  28.         }   
  29.     }   
  30. }   

 测试类

Java代码
  1. package com.test.TestSpring3;   
  2.   
  3. import org.springframework.beans.factory.BeanFactory;   
  4.   
  5. import org.springframework.beans.factory.xml.XmlBeanFactory;   
  6. import org.springframework.context.ApplicationContext;   
  7. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  8. import org.springframework.context.support.FileSystemXmlApplicationContext;   
  9. import org.springframework.core.io.ClassPathResource;   
  10. import org.springframework.core.io.Resource;   
  11. import org.springframework.web.context.support.WebApplicationContextUtils;   
  12.   
  13. public class TestInterceptor ...{   
  14.   
  15.     public static void main(String[] args) ...{   
  16.         ApplicationContext ctx = new FileSystemXmlApplicationContext(   
  17.                 "classpath:applicationContext.xml");   
  18. //        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");      
  19.            
  20.         UserService us = (UserService) ctx.getBean("userService");   
  21.         us.printUser("shawn");   
  22.   
  23.     }   
  24. }

配置文件  

Xml代码
  1. <SPAN style="FONT-SIZE: medium"><?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3. <beans>  
  4.     <bean id="userServiceImp"  
  5.         class="com.test.TestSpring3.UserServiceImp" />  
  6.   
  7.     <bean id="userInterceptor" class="com.test.TestSpring3.UserInterceptor" />  
  8.   
  9.     <bean id="userService"  
  10.         class="org.springframework.aop.framework.ProxyFactoryBean">  
  11.       <!-- 代理接口 -->  
  12.         <property name="proxyInterfaces">  
  13.             <value>com.test.TestSpring3.UserService</value>  
  14.         </property>  
  15.        <!-- 目标实现类 -->  
  16.         <property name="target">  
  17.             <ref local="userServiceImp" />    
  18.       </property>  
  19.         <!-- 拦截器 -->  
  20.         <property name="interceptorNames">  
  21.             <list>  
  22.                 <value>userInterceptor</value>  
  23.             </list>  
  24.         </property>  
  25.     </bean>  
  26.   
  27. </beans>  
  28. </SPAN>  
[xml] view plain copy print ?
  1.    

 

 输出:
  user:shawn
   printUser---!
  printUser user:hello! 

 

结论:调用方法的时候 传入的值被拦截修改了

你可能感兴趣的:(Spring AOP原理及拦截器(aop配置最简单,利用环绕也能实现))