Spring之AOP

[TOC]

AOP(又名AspectJ)

面向切面编程,就是说解决代码复用,代码重复问题。AOP专门用于处理系统中分布于各个模块中的交叉问题

  • 下载安装
  • Eclipse导入Spring-AOP
  • AspectJ使用
  • AOP概念
  • AOP注解方式
  • AOPXML方式

下载安装

AspectJ下载与安装

  1. 地址:http://www.eclipse.org/aspectj/downloads.php
  2. 得到aspectJ-X.X.X.jar文件,然后解压,安装
  3. 安装完成后将 ==安装路径\bin== 添加到PATH环境变量中去,将==安装路径\lib\aspectjrt.jar== 添加到CLASSPATH环境变量中去

AJDT(AspectJ Develoment Tools)下载安装

  1. 这里下载http://www.eclipse.org/ajdt/downloads/ 一定要对应eclipse的版本,比如eclipse4.3对应aspectJ版本
  2. 有两种安装方式:
    1. 第一种:把下载解压后的文件,如:ajdt_2.2.3_for_eclipse_4.3 里的features文件下的所有东西复制粘贴到eclipse的feature文件下,还有plugins这个文件一样
    2. 第二种:在eclipse中Help->Install New SoftWare->Add->选择下载好的压缩包,然后click确定,再重启eclipse就可以了
  3. 使用时,对于一般Java项目,可以右键->Configure->Convert to AspectJ 就可以了

    Eclipse XML配置Spring-AOP的命名空间

  4. (Eclipse项目包中的LIbraries)在spring.jar文件中的META—INF目录中提供了spring.schemas文件,这个文件指定了提供支持的功能的xml元素配置的命名空间定义文件的位置,在这个文件中我们可以找到aop的位置
    image
  5. 在XML文件中引入
    1
    <xmlns:aop="http://www.springframework.org/schema/aop">

之后需要在xsi:schemaLocation 中添加位置:

1
http://www.springframework.org/schema/aop(空格)http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

而/spring-aop-2.5.xsd就是aop的元素的定义的文件名

AspectJ使用

在AOP中Java类仍然是普通Java,可以通过编译运行

  1. 写几个普通Java类,如

    1
    2
    3
    public class Hello(){
    ...
    }
  2. 写AspectJ,如

    1
    2
    3
    public aspect AuthAspect{

    }

==注意:aspect不用参数==

  1. 点击运行

说一下使用的背后:在已经写好的Java类中各自含有不同的方法,但现在想要在每个方法中添加一段代码,以实现某个检测功能,此时使用AspectJ切面编程能够指定在Java类中添加处理,就类似于一刀切,在每个类的Before或者After或者Around范围进行统一的处理,就不用一个一个地去添加处理代码,更好地实现了代码复用.

AOP概念

特征:

  • 各步骤间良好隔离性
  • 源代码无关性(减少了代码污染)

专业术语:

  • 切面(aspect): 组织对个处理,如:

    1
    2
    3
    public aspect HelloTest{
    //其中aspect就是指切面
    }
  • 连接点(joinpoint): 方法的调用,如:

    1
    2
    3
    4
    @Before("execution(* org.dbw.app.service.*.*(..))")
    public void authority(JoinPoint jp){
    //连接点主要作为参数,使用JoinPoint里的proceed()方法
    }
  • 增强处理(Advice): 有around,after,before等类型,如:

    1
    2
    3
    4
    5
    6
    7
    before():execution(* org.dbw.app.service.*.*(..))
    after():............
    around():...........
    //第一个* 为返回类型,如int,double等等
    //第二个* 为任意类,如Hello类,World类等等
    //第三个* 为任意方法,如foo()等等
    //括号里为参数
  • 切入点(Poincut): 可以插入增强处理(Advice)的连接点,就是说当某个连接点满足某个条件,连接点被添加进增强处理(Advice)时,该连接点编程切入点。如:

    1
    2
    poincut xxxPoincut():execution(void Org.dbw*.say*())       
    //每个方法被调用时都是连接点,如调用void dbwLove.sayLove()方法,此时为连接点(Joincut),但因为加入了增强处理,所以变成了切入点.

AOP注解

在Eclipse中添加了aop命名空间后才可以进行操作
启动@Aspect支持

1
<aop:aspectj-autoproxy/>

1. 定义切面Bean

在Spring容器中配置一个带 ==@Aspect== 注解的Bean,Spring将会自动识别该Bean,并将该Bean作为切面处理,且不会对该Bean进行增强处理(Advice)

1
2
3
4
@Asppect
public class LogAspect{
//其他内容
}

2. 定义Before增强处理

用 ==@Before== 修饰一个方法,该方法作为Before增强处理,在目标方法执行前执行所修饰的方法。通常指定一个 ==value属性值== ,该属性值指定一个切入点表达式.

1
2
3
4
5
6
7
@Aspect
public class AuthAspect{
@Before("execution(* org.dbw.app.service.*.*(..))")
public void authority(){
//其他内容
}
}

3. 定义AfterReturning增强处理

使用 ==@AfterReturn== 修饰一个方法,使其成为AfterReturn增强处理,在目标方法正常完成后执行增强处理。
常用属性:
==pointcut/value==:指定该切入点对应的切入表达式
==returning== :可获得目标方法的返回值,同时用于表示增强处理方法中可定义与这个同名的形参

1
2
3
4
5
6
7
8
9
@Aspect
public class LogAspect{
//定义一个AfterReturnning处理,returning属性指定目标方法返回值
@AfterReturning(returning="rvt",pointcut="execution(* org.dbw.app.service.*.*(..))")
//形参:形参类型会限制目标方法必须返回指定类型的值或没有返回值,与returnning属性值同名
public void log(Object rvt){
System.out.println("目标方法返回值"+ rvt);
}
}

4. 定义AfterThrowing增强处理

使用@AfterThrowing注解修饰一个方法,使其成为AfterThrowing增强处理
常用属性
==pointcut/value== 指定切入点对应的切入表达式
==throwing==:指定形参名,该形参用于访问目标方法抛出的异常

1
2
3
4
5
6
7
@Aspect
public class RepairAspect{
@AfterThrowing(throwing="ex" , pointcut="execution(* org.dbw.app.service.*.*(..))")
public void do(Throwable ex){
System.out.println("目标方法抛出的异常"+ex);
}
}

注意:AfterThrowing处理虽然可以对目标方法的异常进行处理,但这种处理与catch不同。catch捕捉是完全处理异常,而AfterThrowing处理虽然处理了异常,但不能完全处理,该异常仍然会抛给上一级调用者.

5. After增强处理

使用@After修饰一个方法,使其成为After增强处理

与AfterReturning区别: ++AfterReturning增强处理只有在目标方法成功完成后才执行++ ,++而After则不管目标方法如何结束,它都会被执行.++

1
2
3
4
5
6
7
@Aspect
public class ReleaseAspect{
@After("execution(* org.dbw.app.service.*.*(..))")
public void release(){
//其他内容
}
}

6. Around处理

使用@Around注解处理,使被修饰方法成为Around处理,近似等于Before和After总和,可以决定目标方法什么时候执行,如何执行,可以阻止目标方法执行。(详细见解看轻量级JavaEE企业应用实战P659)

用法:当定义一个Around Advice时,==第一个形参必须是ProceedingJoinPoint类型== ++(就是说至少包含一个形参)++ ,调用ProceedingJoinPoint参数的proceed()方法时,还可以传入一个Object[]对象作为参数,该数组中的值将被传入目标方法作为执行目标方法的实参。

1
2
3
4
5
6
7
8
9
10
11
12
@Aspect
public class TxAspect{
@Around("execution(* org.dbw.app.service.*.*(..))")
public Object processTx(ProceedingJoinPoint jp){
s.out.print("执行目标方法前");
//创建一个这样的数组,使其成为目标方法的形参
Object[] args = jp.getArgs();
//数组作为proceed方法形参,并用Object保留返回值
Object rvt = jp.proceed(args);
s.out.print("执行目标方法后")
}
}

-------------本文结束感谢您的阅读-------------