1.AOP概念

  AOP(Aspect Oriented Programming):面向切面编程,AOP能够将那些与业务无关,却为业务模块所共同调用的应用(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。  

2.AOP术语  

  通知(Advice)

  在AOP术语中,切面的工作被成为通知。通知定义了切面是什么以及何时使用。

  Spring切面可以应用5种类型的通知:

  • Before —— 在方法被调用之前调用通知;
  • After —— 在方法完成之后调用通知,无论方法执行是否成功;
  • After-returning —— 在方法成功执行之后调用通知;
  • After-throwing —— 在方法抛出异常后调用通知;
  • Around —— 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为;

  连接点(Joinpoint)

  连接点是在应用执行过程中能够插入切面的一个点。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。

  切点(Pointcut)

  如果通知定义了切面的“什么”和“何时”,那么切点就定义了“何处”,即切点用于准确定位应该在什么地方应用切面的通知。

  切面(Aspect)

  切面是通知和切点的结合。通知和切点共同定义了关于切面的全部内容——它是什么,在何时和何处完成其功能。

  引入(Introduction)

  引入允许我们向现有的类添加新方法或属性,通过通知类,从而可以在无需修改现有的类的情况下,让它们具有新的行为和状态(通过使用<aop:declare-parents>声明实现)。

  织入(Weaving)

  织入是将切面应用到目标对象来创建新的代理对象的过程,切面在指定的连接点被织入到目标对象中(注入前置、后置通知等)。

3.使用切点选择连接点  

  Spring AOP中,需要使用AspectJ的切点表达式语言来定义切点。

  Spring仅支持AspectJ切点指示器的一个子集:

Spring AOP支持的AspectJ切点指示符
AspectJ指示器 描述
execution 用于匹配方法执行的连接点
within 用于匹配指定类型内的方法执行
this 用于匹配当前AOP代理对象类型的执行方法,注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配
target 用于匹配当前目标对象类型的执行方法,注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配
args 用于匹配当前执行的方法传入的参数为指定类型的执行方法
@within 用于匹配持有指定注解类型内的方法
@target 用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
@args 用于匹配当前执行的方法传入的参数持有指定注解的执行
@annotation 用于匹配当前执行方法持有指定注解的方法
bean Spring AOP扩展的,用于匹配特定名称的Bean对象的执行方法
reference pointcut 表示引用其他命名切入点

  在Spring中尝试使用其他AspectJ指示器时,将会抛出IllegalArgumentException异常。

  例如,当切点表达式如下时:  

execution(* com.wdcloud.jyx.bj.service.*Service.*(..))

  我们使用execution指示器选择com.wdcloud.jyx.bj.service包下后缀为Service的所有类的所有方法,表达式以*开始,表示我们不关心方法的返回值,而方法参数为(..)表示匹配任意参数的方法。

4.在Spring中配置AOP  

这里介绍两种配置方法:使用xml配置AOP和使用@AspcetJ注解配置AOP,并且还介绍使用@AspcetJ注解配置AOP时如何获取目标方法名、方法参数和方法返回值。

基于xml配置Spring AOP:  

Spring提供了声明式切面的选择。Spring的AOP配置元素简化了基于POJO切面的声明:

AOP配置元素 功能
<aop:advisor> 定义一个AOP通知器
<aop:after> 定义一个AOP后置通知(不考虑被通知的方法是否执行成功,相当于再finally中执行)
<aop:after-returning> 定义一个AOP返回后通知
<aop:after-throwing> 定义一个AOP抛出后通知
<aop:around> 定义一个AOP环绕通知
<aop:aspect> 定义一个切面
<aop:before> 定义一个AOP前置通知
<aop:config> 顶层的AOP元素。大多数<aop:*>元素必须包含在<aop:config>里
<aop:pointcut> 定义一个切点
<aop:declare-parents> 为被通知的对象引入额外的接口,并透明地实现

4.1 引用 aspectJ 的 jar 包: aspectjweaver.jar aspectjrt.jar

4.2 在applicationContext.xml中引入AOP对应的命名空间:

    xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

4.3 创建切面类:

public class LogInterceptor {

    public void before() {
System.out.println("----------method start----------");
} public void after() {
System.out.println("----------method after----------");
} public void AfterReturning() {
System.out.println("----------method AfterReturning----------");
} public void AfterThrowing() {
System.out.println("----------method AfterThrowing----------");
}
}

4.4 在applicationContext.xml中配置AOP

  <!-- spring AOP配置 -->
<bean id="logAdvice" class="com.wdcloud.solr.util.LogInterceptor"/> <aop:config>
<aop:aspect ref="logAdvice">
<aop:pointcut id="pointcut" expression="execution(* com.wdcloud.solr.action.*Action.*(..))" /> <aop:before pointcut-ref="pointcut" method="before" />
<aop:after-returning pointcut-ref="pointcut" method="AfterReturning" />
<aop:after-throwing pointcut-ref="pointcut" method="AfterThrowing" />
</aop:aspect>
</aop:config>

测试结果:

基于@AspcetJ注解配置Spring AOP:

4.1和4.2步骤同上。

4.3 创建切面类:

@Component
@Aspect
public class LogInterceptor { // 定义切点
public static final String actionPointcut = "execution(* com.wdcloud.solr.action.*Action.*(..))"; @Before(actionPointcut)
public void before() {
System.out.println("----------method start----------");
} @After(actionPointcut)
public void after() {
System.out.println("----------method after----------");
} @AfterReturning(actionPointcut)
public void afterReturning() {
System.out.println("----------method AfterReturning----------");
} @AfterThrowing(actionPointcut)
public void afterThrowing() {
System.out.println("----------method AfterThrowing----------");
}
}

4.4 在applicationContext.xml中配置AOP

<!-- 自动为spring容器中那些配置@aspectJ切面的bean创建代理 -->
<!-- proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当poxy-target-class="true"时,表示使用CGLib动态代理技术织入增强 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

测试结果:

使用@AspcetJ注解配置AOP时如何获取目标方法名、方法参数和方法返回值:

访问目标方法最简单的做法是定义切面方法时,将第一个参数定义为JoinPoint类型,当该切面方法被调用时,该JoinPoint参数就代表了织入切面的连接点。JoinPoint里包含了如下几个常用的方法:

  • Object[] getArgs:返回目标方法的参数

  • Signature getSignature:返回目标方法的签名

  • Object getTarget:返回被织入增强处理的目标对象

  • Object getThis:返回AOP框架为目标对象生成的代理对象

将上面的切面类修改如下:

@Component
@Aspect
public class LogInterceptor { // 定义切点
public static final String actionPointcut = "execution(* com.wdcloud.solr.action.*Action.*(..))";
public static final String servicePointcut = "execution(* com.wdcloud.solr.service.*Service.*(..))"; @Before(actionPointcut)
public void before(JoinPoint point) {
System.out.println("----------method " + point.getSignature().getDeclaringTypeName() + "."
+ point.getSignature().getName() + " start----------");
System.out.println("----------param:" + JSONObject.toJSONString(point.getArgs()) + "----------");
} @After(actionPointcut)
public void after(JoinPoint point) {
System.out.println("----------method " + point.getSignature().getDeclaringTypeName() + "."
+ point.getSignature().getName() + " end----------");
} @AfterReturning(pointcut = actionPointcut, returning = "returnValue")
public void afterReturning(JoinPoint point, Object returnValue) {
System.out.println("----------result:" + JSONObject.toJSONString(returnValue) + "----------");
System.out.println("----------method " + point.getSignature().getDeclaringTypeName() + "."
+ point.getSignature().getName() + " end----------");
} //当有多个切点的时候,用"||"连接切点即可
@AfterThrowing(pointcut = actionPointcut + "||" + servicePointcut, throwing = "exception")
public void afterThrowing(JoinPoint point, Exception exception) {
System.out.println("----------exception:" + exception.getMessage() + "----------");
}
}

测试结果:

如果想要在aop中排除某些方法,可以这样配置切点:

public static final String noGetMethodPointcut = "execution(* witparking.starlightmanagement.service.impl.*Service.*(..)) and " +
"!execution(* witparking.starlightmanagement.service.impl.*Service.get*(..))";

参考

http://blog.csdn.net/robinjwong/article/details/25568481#t6

http://www.cnblogs.com/oumyye/p/4480196.html

http://blog.csdn.net/ye_sheng/article/details/48178983

Spring学习笔记2—AOP的更多相关文章

  1. Spring学习笔记之aop动态代理(3)

    Spring学习笔记之aop动态代理(3) 1.0 静态代理模式的缺点: 1.在该系统中有多少的dao就的写多少的proxy,麻烦 2.如果目标接口有方法的改动,则proxy也需要改动. Person ...

  2. Spring学习笔记4——AOP

    AOP 即 Aspect Oriented Program 面向切面编程 首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能. 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务 ...

  3. [Spring学习笔记 4 ] AOP 概念原理以及java动态代理

    一.Spring IoC容器补充(1) Spring IoC容器,DI(依赖注入): 注入的方式:设值方法注入setter(属性注入)/构造子注入(构造函数传入依赖的对象)/字段注入Field(注解) ...

  4. Spring学习笔记之AOP配置篇(一)

    [TOC] 1. 创建并声明一个切面 首先,创建一个类,添加@Component注解使其添加到IoC容器 然后,添加@Aspect注解,使其成为一个切面 最后,在配置文件里面,使用<aop:as ...

  5. spring学习笔记(一) Spring概述

    博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书.  强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...

  6. Java框架spring 学习笔记(十八):事务管理(xml配置文件管理)

    在Java框架spring 学习笔记(十八):事务操作中,有一个问题: package cn.service; import cn.dao.OrderDao; public class OrderSe ...

  7. 不错的Spring学习笔记(转)

    Spring学习笔记(1)----简单的实例 ---------------------------------   首先需要准备Spring包,可从官方网站上下载.   下载解压后,必须的两个包是s ...

  8. 【Spring学习笔记-MVC-5】利用spring MVC框架,实现ajax异步请求以及json数据的返回

    作者:ssslinppp      时间:2015年5月26日 15:32:51 1. 摘要 本文讲解如何利用spring MVC框架,实现ajax异步请求以及json数据的返回. Spring MV ...

  9. 【Spring学习笔记-MVC-3】SpringMVC返回Json数据-方式1

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

随机推荐

  1. Vue 获取验证码倒计时组件

    子组件 <template> <a class="getvalidate":class="{gray: (!stop)}"@click='cl ...

  2. MySQL 使用 比较函数 INTERVAL() 函数 实现数据按区间分组

    首先看一下它的定义: INTERVAL(N,N1,N2,N3,..........) INTERVAL()函数进行比较列表(N1,N2,N3等等)中的N值.该函数如果N<N1返回0,如果N< ...

  3. Hash索引和BTREE索引2

    索引是数据库中用来提高性能的最常用工具.所有MySql列类型都可以被索引.索引用于快速找出在某个列中有一特定值的行.如果不使用索引,MYSQL必须从第一条记录开始然后读完整个表直到找出相关的行.常用的 ...

  4. mysql之log-slave-updates参数

    1.引言 使用Mysql的replication机制实现主从同步时,其是由三个线程实现了,主库一个I/O线程,从库一个I/O线程和一个SQL线程.配置时主库需要开始bin-log参数,即在配置文件中添 ...

  5. cmake工程使用distcc

    distcc可以加速编译,但是遇到cmake可能就需要处理下. 问题 distcc在 /usr/lib/distcc 中放了各编译器的soft link(如cc/gcc等等),如果 /usr/lib/ ...

  6. 2017-5-14 湘潭市赛 Partial Sum 给n个数,每次操作选择一个L,一个R,表示区间左右端点,该操作产生的贡献为[L+1,R]的和的绝对值-C。 0<=L<R<=n; 如果选过L,R这两个位置,那么以后选择的L,R都不可以再选择这两个位置。最多操作m次,求可以获得的 最大贡献和。

    Partial Sum Accepted : Submit : Time Limit : MS Memory Limit : KB Partial Sum Bobo has a integer seq ...

  7. PHP : ActiveRecord实现示例

    先简单介绍一下Active Record: Active Record(中文名:活动记录)是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录.Acti ...

  8. ECharts:企业报表工具

    ECharts.纯Javascript图表库,基于Canvas,底层依赖ZRender.商业产品经常使用图表库,提供直观,生动.可交互,可个性化定制的数据可视化图表.创新的拖拽重计算.数据视图.值域漫 ...

  9. 【OC学习-13】什么是组合,它和继承是什么关系?

    继承有两缺点:(1)当层级越来越多时,假如每一个层级都有实例变量,那么最下层的子类继承的实例变量会超级多,沉重.(2)当消息传递自子类往上时.层级越多,效率越低下. 所以就有了组合.说实话区分继承和组 ...

  10. Apache Nifi 开发

    Apache NiFi是由美国过国家安全局(NSA)贡献给Apache基金会的开源项目.其设计目标是自己主动化系统间的数据流.基于其工作流式的编程理念.NiFi很易于使用,强大.可靠及高可配置. 两个 ...