面向切面编程(AOP)的思想就是在执行某些代码前执行另外的代码,使程序更灵活、扩展性更好,可以随便地添加删除某些功能。

javaweb机制中的filter就是面向切面编程的例子。Tomcat会在程序运行的某个时机(即servlet执行前后),执行与servlet、JSP等毫无关系的filter代码。

AOP把一个业务流程分成几个部分,例如权限检查,业务处理,日志记录,每个部分单独处理,然后把它们组装成完整的业务流程。每个部分被称为切面(Aspect)或者关注点。Spring提供的AOP机制异常灵活,能够在任何类、任何方法的执行前、后添加拦截器。Spring推荐使用接口编程,Spring提供三种拦截器:方法前拦截器、返回后拦截器、异常抛出拦截器。

下面我们从一个简单的例子开始学习spring aop:

//Service接口
public interface IAopService{  public void withAop() throws Exception;         //将会被拦截  public void withoutAop() throws Exception;      //不会被拦截
}  //Service接口 实现类
public class AopServiceImpl implements IAopService{  private String name;  public void withAop() throws Exception{  System.out.println("有AOP的函数运行。name:"+name);  if(name.trim().length() == 0){  throw new AccountException("name属性不能为空");  }  }  public void withoutAop() throws Exception{  System.out.println("没有AOP的函数运行。");  }  public void setName(String name){  this.name = name;  }  public String getName(){  return this.name;  }
}  

方法前拦截器,检查name是否为空:

import  org.springframework.aop.MethodBeforeAdvice;
public class MethodBeforeInterceptor implements MethodBeforeAdvice{  //调用对象的方法前执行该方法  //参数分别为被调用的方法、被调用方法的参数、对象  public void before(Method method,Object [] args,Object instance) throws Throwable{  System.out.println("即将执行方法:"+method.getName());  //  if(instance instanceof AopServiceImpl){  String name = ((AopServiceImpl)instance).getName();  if(name == null){  throw new NullPointerException("name不能为空");  }  }  }  }  

返回后拦截器:

import  org.springframework.aop.AfterReturningAdvice;
public class MethodAfterInteceptor implements AfterReturningAdvice{  //参数分别为方法返回值、被调用方法、方法参数、被拦截的对象  public void afterReturning(Object value,Method method,Object [] args,Object instance) throws Throwable{  System.out.println("方法:"+method.getName()+"执行完毕,返回值为:"+value);  }
} 

异常拦截器捕获异常 :

import  org.springframework.aop.ThrowAdvice;
public class ThrowsInterceptor implements ThrowAdvice{  //参数分别为被调用的方法、方法参数、对象实例、抛出的异常  //前三个参数可以省略,第四个参数是必须的,这样设计是为了使开发者灵活地定义多个方法捕获各种不同的异常  public void afterThrowing(Method method,Object [] args,Object instance,AccountException ex) throws Throwable {  System.out.println("方法:"+method.getName()+"抛出了异常:"+ex);  }  public void afterThrowing(NullPointerException ex) throws Throwable {  System.out.println("抛出了异常:"+ex);  }  }

拦截器配置:
Spring无法将Service的实现类与拦截器直接组装,因为没有对应的setter、getter方法。安装时借助的是Spring的代理类,把拦截器安装到NameMatchMethodPointcutAdvisor中,把自动以的Service安装到ProxyFactoryBean中,然后组装到一块。

<!-- 方法前拦截器MethodBeforeInterceptor安装到NameMatchMethodPointcutAdvisor中 -->
<bean id="aopMethodBeforeInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">  <!--  拦截器的实现类-->  <property name="advice">  <bean class="com.lmb.spring. MethodBeforeInterceptor">  </property>  <!--  欲拦截的方法名-->  <property name="mappedName" value="withAop">  </property>
</bean>  <!-- 类似的方式配置返回后前拦截器MethodAfterInteceptor -->
<bean id="aopMethodAfterInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">  <property name="advice">  <bean class="com.lmb.spring. MethodAfterInteceptor">  </property>  <property name="mappedName" value="withAop">  </property>
</bean>  <!-- 类似的方式配置异常前拦截器MethodAfterInteceptor -->
<bean id="aopThrowsInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">  <property name="advice">  <bean class="com.lmb.spring.ThrowsInterceptor">  </property>  <property name="mappedName" value="withoutAop">   </property>
</bean>  <!-- Service实现类,安装到ProxyFactoryBean -->
<bean id="aopService" class="org.springframework.aop.ProxyFactoryBean">  <!-- 安装拦截器-->  <property name="interceptorNames">  <list>  <value>aopMethodBeforeInterceptor</value>  <value>aopMethodAfterInterceptor</value>  <value>aopThrowsInterceptor</value>  </list>  </property>  <!-- 被拦截的对象-->  <property name="target">  <bean class="com.lmb.spring.AopServiceImpl">  <property name="name" value="HelloSpring"></property>  </bean>  </property>
</bean>  

切面Aspect:在本例中,方法withAop()、withoutAop()中都有一些代码,这些代码可以看做是AOP中的切面,可以将切面理解为模块;

通知Advisor:本例的三个拦截器都是实现自某个接口,从类名上看就知道三个拦截器都是AOP中的通知。一旦Spring符合条件,就会派发出通知,即一些需要执行的代码,能实现某种功能;

切入点Pointcut:在配置拦截器时,XML中只配置了withAop()方法使用拦截器,而withoutAop()方法没有配置拦截器,这种配置是借助于org.springframework.aop.support. NameMatchMethodPointcutAdvisor完成的。这就是一个切入点,配置时可以使用通配符。该类说明上也带有Advisor是因为它也是用通知实现的;

AOP的相关概念总结:

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用spring的 Advisor或拦截器实现。

连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice。

切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上。

引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口。

目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。

AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

【Spring学习】Spring的AOP模块应用详解相关推荐

  1. Spring学习(七)bean装配详解之 【通过注解装配 Bean】【自动装配的歧义解决】...

    本文借鉴:Spring学习,@Bean 的用法(特此感谢!) 自动装配 1.歧义性 我们知道用@Autowired可以对bean进行注入(按照type注入),但如果有两个相同类型的bean在IOC容器 ...

  2. Spring学习(六)bean装配详解之 【通过注解装配 Bean】【基础配置方式】

    本文借鉴:Spring学习(特此感谢!) 通过注解装配 Bean 1.前言 优势 1.可以减少 XML 的配置,当配置项多的时候,XML配置过多会导致项目臃肿难以维护 2.功能更加强大,既能实现 XM ...

  3. Spring学习(五)bean装配详解之 【XML方式配置】

    本文借鉴:Spring学习(特此感谢!) 一.配置Bean的方式及选择 配置方式 在 XML 文件中显式配置 在 Java 的接口和类中实现配置 隐式 Bean 的发现机制和自动装配原则 方式选择的原 ...

  4. spring学习(8):log4j.properties 详解与配置步骤

    一.入门实例 1.新建一个JAva工程,导入包log4j-1.2.17.jar,整个工程最终目录如下 2.src同级创建并设置log4j.properties ### 设置### log4j.root ...

  5. Spring Boot的每个模块包详解

    Spring Boot的每个模块包详解,具体如下: 1.spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. 2.spring-boot-s ...

  6. 跟着小马哥学系列之 Spring AOP(Advisor 详解)

    学好路更宽,钱多少加班. --小马哥 简介 大家好,我是小马哥成千上万粉丝中的一员!2019年8月有幸在叩丁狼教育举办的猿圈活动中知道有这么一位大咖,从此结下了不解之缘!此系列在多次学习极客时间< ...

  7. Spring基于注解TestContext 测试框架使用详解

    原创整理不易,转载请注明出处:Spring基于注解TestContext 测试框架使用详解 代码下载地址:http://www.zuidaima.com/share/1775574182939648. ...

  8. Spring Boot 使用 HikariCP 连接池配置详解

    Spring Boot 使用 HikariCP 连接池配置详解 HikariCP 是一个高性能的 JDBC 连接池组件. Spring Boot 2.x 将其作为默认的连接池组件,项目中添加 spri ...

  9. Spring三级缓存解决循环依赖问题详解

    spring三级缓存解决循环依赖问题详解 前言 这段时间阅读了spring IOC部分的源码.在学习过程中,自己有遇到过很多很问题,在上网查阅资料的时候,发现很难找到一份比较全面的解答.现在自己刚学习 ...

最新文章

  1. 局域网与网络工程课堂笔记(1)(2)
  2. PHP性能调优,PHP慢日志---PHP脚本执行效率性能检测之WebGrind的使用
  3. 【错误记录】Mac 中 IntelliJ IDEA 运行 Python 程序报错 ( End of statement expected )
  4. LeetCode算法题5:双指针
  5. VTK:图片之ResizeImage
  6. Qt工作笔记-对QThread使用的进一步认识(exec及对象在哪个线程创建)
  7. (转) 淘淘商城系列——CMS内容管理系统工程搭建
  8. 剑桥女博士创立情绪识别 AI 公司,帮助自闭症患者理解他人表情
  9. 了解 PerformancePoint 仪表板设计器
  10. C编程语言中整型变量在内存中的存储形式介绍
  11. BZOJ_1029_[JSOI2007]_建筑抢修_(贪心+优先队列)
  12. 学习矩阵分析与应用过程中的点滴记录(一)
  13. catia设计树_在CATIA目录树上**零件号原来这么简单!
  14. 笔记本电脑切换Fn功能键
  15. 自上而下 or 自下而上?企业部署RPA的2种策略
  16. 阿里云账号注册实名认证详细教程(支付宝实名认证)
  17. 家用洗地机有什么优缺点?入门级家用洗地机
  18. 模块内高内聚?模块间低耦合?MVC+EF演示给你看!
  19. pg批量插入_postgresql大批量数据导入方法
  20. java程序设计 秒表计时器_【Java】Java计时器(秒表)

热门文章

  1. ubuntu下安装openfetion
  2. 走向.NET架构设计—第四章—业务层分层架构(前篇)
  3. WebKit 内核源码分析 (三) Page
  4. 【转】路由转发过程的IP及MAC地址变化
  5. linux解压war包的命令
  6. ssm(Spring、Springmvc、Mybatis)实战之淘淘商城-第七天(非原创)
  7. uwsgi xml 配置
  8. OpenGL 笔记1 固定管线实例 + 双缓存测试实例
  9. js array 的理解
  10. Visula Basic程序设计理论与实践pdf