Spring对AOP的支持<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
4.1 AOP介绍
首先让我们从一些重要的AOP概念和术语开始。这些术语不是Spring特有的。不过AOP术语并不是特别的直观,如果Spring使用自己的术语,将会变得更加令人困惑。
·         切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现。
·         连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。
·         通知(Advice):在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知(通知的类型将在后面部分进行讨论)。许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。
·         切入点(Pointcut):匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
·         引入(Introduction):用来给一个类型声明额外的方法或属性(也被称为连接类型声明(inter-type declaration))。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用引入来使一个bean实现IsModified接口,以便简化缓存机制。
·         目标对象(Target Object): 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。
·         AOP代理(AOP Proxy):AOP框架创建的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
·         织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
通知类型:
  • 前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
  • 后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
  • 异常通知(After throwing advice):在方法抛出异常退出时执行的通知。
  • 最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • 环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。
    环绕通知是最常用的通知类型。和AspectJ一样,Spring提供所有类型的通知,我们推荐你使用尽可能简单的通知类型来实现需要的功能。例如,如果你只是需要一个方法的返回值来更新缓存,最好使用后置通知而不是环绕通知,尽管环绕通知也能完成同样的事情。用最合适的通知类型可以使得编程模型变得简单,并且能够避免很多潜在的错误。比如,你不需要在JoinPoint上调用用于环绕通知的proceed()方法,就不会有调用的问题。在Spring 2.0中,所有的通知参数都是静态类型,因此你可以使用合适的类型(例如一个方法执行后的返回值类型)作为通知的参数而不是使用Object数组。 通过切入点匹配连接点的概念是AOP的关键,这使得AOP不同于其它仅仅提供拦截功能的旧技术。 切入点使得通知可以独立对应到面向对象的层次结构中。例如,一个提供声明式事务管理的环绕通知可以被应用到一组横跨多个对象的方法上(例如服务层的所有业务操作)。
    4.2 创建通知
       我们通过一个简单的例子来理解AOP。
       代码清单1
public class Foo {
    public void printName(String name){
       System.out.println("The Name is : " + name);
    }
    public void printAge(String age){
       System.out.println("The Age is : " + age);
    }
}
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class FooBeforeAdvice implements MethodBeforeAdvice{
    @Override
    public void before(Method method, Object[] args, Object object)
           throws Throwable {
       //打印出类的名称
       System.out.print("Class Name is " +
                     object.getClass().getSimpleName() + " ");
       //打印出参数的值
       System.out.println("arg is "+(String)args[0] + " ");
    }
}
import org.springframework.aop.framework.ProxyFactory;
public class Test {
    public static void main(String[] args) {
       Foo foo = new Foo();
       FooBeforeAdvice advice = new FooBeforeAdvice();
       //Spring提供的代理工厂
       ProxyFactory pf = new ProxyFactory();
       //设置代理目标
       pf.setTarget(foo);
       //为代理目标添加增强
       pf.addAdvice(advice);
       //生成代理实例
       Foo proxy = (Foo)pf.getProxy();
       proxy.printName("Tony");
       proxy.printAge("27");
    }  
}
控制台输出信息
Class Name is Foo arg is Tony
The Name is : Tony
Class Name is Foo arg is 27
The Age is : 27
代码清单1中我们的Foo.java类有两个方法,我们创建了FooBeforeAdvice继承前置增强接口MethodBeforeAdvice,在before方法中我同通过参数object获得代理的对象信息,通过参数args获得代理方法的参数值,最后我们通过ProxyFactory将目标类和增强类融合,生成了代理实例并调用代理实例的方法。而在Spring中又如何配置AOP呢?
4.3前置增强
代码清单2
<bean id="foo" class="com.tony.test.Foo" scope="singleton"/>
<bean id="fooBeforeAdvice" class="com.tony.test.FooBeforeAdvice"/>
<bean id="proxy"
       class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="interceptorNames"><!-- 指定增强 -->
       <list>
           <value>fooBeforeAdvice</value>
       </list>
    </property>
    <!-- 指定目标代理Bean -->
    <property name="target" ref="foo"/>
</bean>
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class Test {
    public static void main(String[] args) {
       ClassPathResource resource = new
                  ClassPathResource("spring-config-beans.xml");
       //实例化BeanFactory
       BeanFactory factory = new XmlBeanFactory(resource);
       Foo foo = (Foo)factory.getBean("proxy");
       foo.printName("Tony");
       foo.printAge("27");
    }  
}
控制台信息
Class Name is Foo arg is Tony
The Name is : Tony
Class Name is Foo arg is 27
The Age is : 27
代码清单2中我们只需修改Spring的配置文件,将增强类和目标类装配起来就可以了,我们在Test.java就像正常的调用Foo一样,可是控制台取已经是被拦截了。
4.4后置增强
代码清单1
public class Foo {
    public String printName(String name){
       return "The Name is : " + name;
    }
    public String printAge(String age){
       return "The Age is : " + age;
    }
}
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class FooAfterAdvice implements AfterReturningAdvice{
    @Override//参数分别是代理方法的返回值,被代理的方法,方法的参数,代理对象
    public void afterReturning(Object returnValue, Method method,
                   Object[] args,Object object) throws Throwable {
       //打印出类的名称
       System.out.print("Class Name is " +
                         object.getClass().getSimpleName() + " ");
       //打印出参数的值
       System.out.println("arg is "+
                          (String)args[0] + " ");
       //打印出返回值图
       System.out.println("ReturnValue is " +
                            returnValue.toString());
    }
}
<bean id="foo" class="com.tony.test.Foo" scope="singleton"/>
<bean id="fooAfterAdvice" class="com.tony.test.FooAfterAdvice"/>
<bean id="proxy"
       class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="interceptorNames"><!-- 指定增强 -->
       <list>
           <value>fooAfterAdvice</value>
       </list>
    </property>
    <!-- 指定目标代理Bean -->
    <property name="target" ref="foo"/>
</bean>
控制台输出
Class Name is Foo arg is Tony
ReturnValue is The Name is : Tony
Class Name is Foo arg is 27
ReturnValue is The Age is : 27
代码清单中我们修改了Foo.java类两个方法都返回String类型的参数,定义了一个FooAfterAdvice.java类这个类实现了AfterReturningAdvice接口,分别打印出被代理类的名称,方法参数值和返回值。我们查看控制台输出的信息,发现在目标方法执行结束后还打印出增强类输出的信息。
4.5环绕增强
代码清单1
public class Foo {
    public void printName(String name){
       System.out.println("The Name is : " + name);
    }
    public void printAge(String age){
       System.out.println("The Age is : " + age);
    }
}
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class FooInterceptor implements MethodInterceptor{
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
       //目标方法入参
       Object[] args = invocation.getArguments();
       //打印方法入参
       System.out.println("准备执行目标方法");
       //执行目标方法
       Object obj = invocation.proceed();
       System.out.println("目标方法执行完成");
       //返回方法返回值
       return obj;
    }
}
<bean id="foo" class="com.tony.test.Foo" scope="singleton"/>
<bean id="fooInterceptor" class="com.tony.test.FooInterceptor"/>
<bean id="fooAfterAdvice" class="com.tony.test.FooAfterAdvice"/>
<bean id="proxy"
       class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="interceptorNames"><!-- 指定增强 -->
       <list>
           <value>fooInterceptor</value>
       </list>
    </property>
    <!-- 指定目标代理Bean -->
    <property name="target" ref="foo"/>
</bean>
控制台输出
准备执行目标方法
The Name is : Tony
目标方法执行完成
准备执行目标方法
The Age is : 27
目标方法执行完成
代码清单1中我们定义了FooInterceptor.java实现MethodInterceptor接口对目标方法进行环绕增强,查看控制台我们就能看出FooInterceptor在每次方法的执行前后都进行了处理。

我的其它Spring文章,也许会对您有帮助

 

Spring的任务调度和邮件发送

 

Spring应用的单元测试

 

Spring的数据库支持

 

Spring的MVC框架

 

Spring的IoC容器

 

Spring对AOP的支持

 

Spring2.5注释驱动与基于注释的MVC

 

转载于:https://blog.51cto.com/tonyaction/85504

Spring对AOP的支持相关推荐

  1. Spring中的AOP(二)——AOP基本概念和Spring对AOP的支持

    AOP的基本概念 AOP从运行的角度考虑程序的流程,提取业务处理过程的切面.AOP面向的是程序运行中的各个步骤,希望以更好的方式来组合业务逻辑的各个步骤.AOP框架并不与特定的代码耦合,AOP框架能处 ...

  2. spring(4)面向切面的Spring(AOP)

    [0]README 1)本文部分文字描述转自:"Spring In Action(中/英文版)",旨在review  "spring(4)面向切面的Spring(AOP) ...

  3. Spring框架 AOP面向切面编程(转)

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  4. Spring 使用AOP

    AOP是Aspect Oriented Programming,即面向切面编程. 那什么是AOP? 我们先回顾一下OOP:Object Oriented Programming,OOP作为面向对象编程 ...

  5. 【Spring】AOP - 面向切面

    面向切面 - AOP 切面实现了横切关注点(跨越多个应用对象的逻辑)的模块化: 术语 通知(Advice) 在AOP术语中,切面的工作被成为通知.通知定义了切面是什么以及何时使用. Spring切面可 ...

  6. Spring–添加AOP支持

    我听到了一个有关一位高级(且酬劳颇丰)软件工程师的故事. 他的任务是记录他正在研究的项目中每个控制器中的每个方法. 工程师重写了所有控制器方法,因此使用如下代码: @RequestMapping(me ...

  7. Java缓存学习之五:spring 对缓存的支持

    (注意标题,Spring对缓存的支持 这里不单单指Ehcache ) 从3.1开始,Spring引入了对Cache的支持.其使用方法和原理都类似于Spring对事务管理的支持.Spring Cache ...

  8. [Spring 深度解析]第4章 Spring之AOP

    第4章 ◄Spring之AOP► 在上一章节中,我们大致了解了Spring核心容器,了解了IOC思想在Spring中的具体应用Bean容器以及Bean的配置与使用,这一章我们将开始学习AOP在Spri ...

  9. 【SSM框架系列】Spring 的 AOP(面向切面编程)

    什么是 AOP AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP 是 OOP ...

最新文章

  1. <论文阅读>CascadePSP: Toward Class-Agnostic and Very High-Resolution Segmentation via Global and...
  2. java生成缩略图类源码
  3. flexi-streams用法简介
  4. 浅谈ATP检查中的“确认可用部分数量”(一)
  5. Window系统下安装Redis
  6. JS前端常用工具方法
  7. 今天看到一篇小册子上的话
  8. Android 8.0学习(8)---内核文件系统优化
  9. 小米盗图迪丽热巴?公关经理:占位示意 不存在故意盗图!
  10. 360能卸载oracle,如何完全卸载Oracle
  11. 面试稳了!BATJ 等大厂 400+ 道面试题全汇总!
  12. 解决PL/SQL查询结果乱码的问题
  13. JAVA几何图注水,Java学习:使用Graphics2D类画的简易土星图案
  14. DBC2000是什么?DBC2000数据库文件超详细讲解
  15. 【CPLEX】Java调用CPLEX的一些小笔记
  16. 两个华为路由器实现MESH组网,WIFI信号无缝漫游
  17. win10文件资源管理器默认打开我的电脑及左侧导航设置
  18. postman面试_接口测试面试常见问题
  19. 多模光纤与单模光纤熔接及用哪种光模块的问题。
  20. 量子计算机 国外大学,全球首款纯硅量子计算机芯片在新南威尔士大学诞生

热门文章

  1. FPGA之道(80)静态时序分析(六)常用时序约束介绍(基于ISE的UCF文件语法)
  2. 基于FPGA的IP核RAM的设计和调用
  3. Replication Controller、Replica Set
  4. 《jQuery Mobile入门经典》—— 2.7 练习
  5. Oracle动态采样学习
  6. Tornado框架中视图模板Template的使用
  7. 海量数据处理的思路和方法
  8. ACM网络赛金华赛区的一道关于树的题:Family Name List
  9. 9月份准备备考RHCE 10份考试争取一次通过
  10. 定位城市_北方城市如何利用GPS定位器减轻铲雪工作压力?