文档章节

Spring的学习(七):AOP

yuhuan121
 yuhuan121
发布于 2017/08/28 02:09
字数 2328
阅读 3
收藏 0

1、定义

AOP(Aspect Orient Programming):面向切面编程,是OOP(Object Oriented Programming,面向对象编程)的一种补充,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。OOP将程序分解成各个层次的对象,从静态的角度来考虑程序结构;AOP是将程序的运行过程分为各个切面,从动态的角度考虑程序的运行过程。

2、为什么要用AOP呢?

先列几段代码: 定义一个接口

package org.crazyit.spring.aop.service;
public interface AritithmeticCalculator{
	int add(int i,int j);
	int sub(int i,int j);
	int mul(int i,int j);
	int div(int i,int j);
}

定义接口的实现类

package org.crazyit.spring.aop.service;

public class AritithmeticCalculatorImpl implements AritithmeticCalculator {

	@Override
	public int add(int i, int j) {
		System.out.println("加法开始["+i+","+j+"]");
		int result = i + j;
		System.out.println("加法结束"+result);
		return result;
	}

	@Override
	public int sub(int i, int j) {
		System.out.println("减法开始["+i+","+j+"]");
		int result = i - j;
		System.out.println("减法结束"+result);
		return result;
	}

	@Override
	public int mul(int i, int j) {
		System.out.println("乘法开始["+i+","+j+"]");
		int result = i * j;
		System.out.println("乘法结束"+result);
		return result;
	}

	@Override
	public int div(int i, int j) {
		System.out.println("除法开始["+i+","+j+"]");
		int result = i / j;
		System.out.println("除法结束"+result);
		return result;
	}
}

主程序

package org.crazyit.spring.aop.service;

public class Main {
	public static void main(String[] args){
		AritithmeticCalculator aritithmeticCalculator = new AritithmeticCalculatorImpl();
		int result = aritithmeticCalculator.add(1, 2);
		System.out.println("-->" + result);
		result = aritithmeticCalculator.div(5, 2);
		System.out.println("-->" + result);
	}
}

输出 输入图片说明 本例中每个方法开始结束之前都写了日志代码,且类似,每次都要写,很麻烦。而且,导致核心代码占得篇幅较小,造成了代码混乱且分散。越来越多的非业务需求(日志和验证等)加入后, 原有的业务方法急剧膨胀。 每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点.。以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块(方法)里多次重复相同的日志代码。如果日志需求发生变化, 必须修改所有模块。

AOP 的主要编程对象是切面(aspect), 而切面模块化横切关注点。 在应用 AOP 编程时,仍然需要定义公共功能, 但可以明确的定义这个功能在哪里, 以什么方式应用, 并且不必修改受影响的类。 这样一来横切关注点就被模块化到特殊的对象(切面)里。 AOP 的好处:

  • 每个事物逻辑位于一个位置, 代码不分散, 便于维护和升级
  • 业务模块更简洁, 只包含核心业务代码

AOP框架的特征:

  • 各步骤之间有良好的隔离性
  • 与源代码无关

可以使用AspectJ来实现AOP,它是基于Java语言的AOP框架。

3、基本概念

横切关注点:对哪些方法进行拦截,拦截后怎么处理;

切面(Aspect): 横切关注点被模块化的特殊对象;

目标(Target): 被通知的对象;

代理(Proxy): 向目标对象应用通知之后创建的对象;

连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;相对点表示的方位;

增强处理(Advice):AOP框架在特定的切入点执行的增强处理。这些处理的类型有“around”、“before"、”after“等类型;

切点(pointcut):可以插入增强处理的连接点;

织入(Weaving):将增强对象添加到目标对象中,并创建一个被增强的对象的过程;

AOP需要程序猿参与的只有三个部分:

  • 定义普通的业务组件;
  • 定义切入点,一个切入点可能横切好几个业务组件;
  • 定义增强处理

关于定义切入点和增强处理,可以用AspectJ来实现;具体可用两种方式:

  • 基于注解的“零配置“方式:使用@Aspect、@Pointcut等注解;
  • 基于XML配置文件的管理方式;

4、基于注解的“零配置“方式

在 Spring IOC 容器中启用 AspectJ 注解支持, 要在 Bean 配置文件中定义一个空的 XML 元素 aop:aspectj-autoproxy,当 Spring IOC 容器侦测到 它时, 会自动为与 AspectJ 切面匹配的 Bean 创建代理。

4.1、定义切面类

使用@Aspect标注一个Java类,这个类会作为切面类;当spring容器检测到某个类使用了此标注后,不会对该类进行增强处理。

//使用@Aspect定义一个切面类
@Aspect
public class LogAspect{
    ...
}

4.2、定义before增强处理

@Before一般用于一个切面类里,用于修饰一个方法,该方法作为Before增强处理。@Before一般有个value值,指定一个切入点表达式,用于指定该增强处理被用于那些切入点。

4.3、定义AfterReturning增强处理

AfterReturning增强处理将在目标方法正常完成后织入 @AfterReturning有两个属性:

  • point/value:指定该切入点对应的切入点表达式;
  • returning:指定一个形参名,表示Advice方法中可以定义同名的形参名,用于访问目标方法的返回值。在Advice方法中还要指定形参名对应的类型,限定目标方法必须返回指定的类型或无返回值。

4.4、定义AfterThrowing增强处理

用于处理程序中未处理的异常

@AfterThrowing也有两个属性

  • point/value:指定该切入点对应的切入点表达式;
  • throwing:指定一个形参名,表示Advice方法中可以定义同名的形参名,用于访问目标方法抛出的异常。在Advice方法中还要指定形参名对应的类型,限定目标方法必须抛出指定的异常。

4.5、定义After增强处理

和AfterReturning不同的是,AfterReturning只有在目标方法完成之后才会被织入;After不管目标方法怎样结束,都会被织入,包括成功完成和异常终止两种情况。用于处理程序中正常返回和异常返回两种情况。

@After也需要一个value属性,值可以是一个已有的切入点还可以是切入点表达式;

4.6、定义Around增强处理

功能较强大:既可以在执行目标方法之前织入增强动作,也可以在执行之后,也可以阻止目标方法的执行;可以改变目标方法的参数值,也可以改变它的返回值。

也需要一个value属性,值可以是一个已有的切入点还可以是切入点表达式;

4.7、定义切入点

两个部分

  • 切入点表达式:指定该切入点和哪些方法匹配;通常用@Pointcut标注
  • 切入点签名:包含名字和任意参数

例:@Pointcut("execution(* transfer(..))") 匹配任何名为transfer的方法的执行

4.8、切入点指示符

4.8.1、execution

用于匹配执行方法的连接点

格式:

execution(a? b c? d(e) f)
  • a:指定方法的修饰符,支持通配符,可省略;
  • b:指定方法的返回值类型,支持通配符,可以用* 代表所有类型
  • c:指定方法所属的类,支持通配符,可省略;
  • d:指定匹配指定的方法名,可用*代表全部;
  • e:方法的形参,支持两个通配符*和.. 前面代表所有,后面代表0个或多个
  • f:指定方法声明抛出的异常,可省略;

4.8.2、with

用于限定匹配特定类型的连接点;

4.8.3、this

用于限定AOP代理必须是指定类型的实例,匹配该对象的所有连接点;

4.8.4、target

用于限定目标对象必须是指定类型的实例,匹配该对象的所有连接点;

4.8.5、args

用于限定连接点的参数类型;

4.8.6、Bean

用于限定匹配特定Bean实例内的连接点,只能使用方法执行作为连接点;

4.8、组合切入点表达式

用三个逻辑运算符 && 、||、!

5、基于XML配置文件的管理方式

没有使用JDK1.5以上版本就要用这种

5.1、配置切面

aop:aspect.../元素,有三个属性:

  • id :该切面的标识名
  • ref:用于将此属性所引用的普通Bean转换为切面Bean;
  • order:指定切面Bean的优先级,值越小优先级越高;

5.2、配置增强处理

aop:before.../aop:after.../aop:after-returning.../aop:after-throwing.../aop:around.../ 有以下属性:

  • pointcut:指定一个切入点表达式;
  • pointcut-ref:指定一个已经确定存在的切入点名称;和上面一个属性两者使用其一;
  • method:指定一个方法名;
  • throwing:只对aop:after-throwing.../有效,指定一个形参名,AfterThrowing增强处理方法可以通过该形参访问目标方法抛出的异常;
  • returning:只对aop:after-returning.../有效,指定一个形参名,AfterReturning增强处理方法可以通过该形参访问目标方法的返回值;

5.3、配置切入点

aop:pointcut../元素定义切入点,当它作为aop:config../元素的子元素时,表明该切入点可被多个切面共享;当它作为aop:aspect../元素的子元素时,表明该切入点只能在该切入点有效;

属性:

  • id:切入点的标识名;
  • expression:指定该切入点关联的切入点表达式;

© 著作权归作者所有

共有 人打赏支持
yuhuan121
粉丝 0
博文 36
码字总数 38704
作品 0
佛山
程序员
私信 提问
Spring 源码解读 推荐流程

Spring源代码解析(一):IOC容器:http://www.javaeye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.javaeye.com/topic/86594 Spring源代码解析(三):Sprin...

2k10
2015/04/02
0
0
那些年,我们一起追的Spring

学无止境,但仍需及时总结。 自去年开始写作以来,写了一些关于Spring的文章,今天将它们汇总起来,一方面方便大家阅读,另一方面,也是一次小的复盘总结。 IOC 首先是Spring的IOC,也就是控...

SexyCode
08/14
0
0
Spring AOP 的实现方式(以日志管理为例)

Spring AOP 的实现方式(以日志管理为例) 2016年10月08日 00:13:57 阅读数:23198 在学习Spring框架的历程中,最重要的是要理解Spring的IOC和AOP了,不但要学会怎么用,最好是知道它是怎么实...

Jeam_
07/04
0
0
Aspectj与Spring AOP比较

1、简介 今天有多个可用的 AOP 库, 它们需要能够回答许多问题: 是否与用户现有的或新的应用程序兼容? 在哪里可以实现 AOP? 与自己的应用程序集成多快? 性能开销是多少? 在本文中, 我们将...

沈渊
04/18
0
0
Spring中的AOP(七)——基于XML配置文件方式的AOP

除了前面介绍的基于JDK1.5的注解方式来定义切面,切入点和增强处理外,Spring AOP也允许直接使用XML配置文件来管理它们。在JDK1.5之前,只能使用配置文件的方式来管理,在Spring2.X后提供了一...

摆渡者
2014/03/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

new Date() 在Safari下的 Invalid Date问题

问题复现 var timeStr = '2018-11-11 00:00:00';var time = new Date(timeStr);// error: Invalid Date... 在safari浏览器下,time为Invalid Date, 导致后面代码执行错误; 其他浏览器诸...

会写代码的husky
21分钟前
2
0
0009-如何升级Cloudera Manager和CDH

1.文档编写目的 本文档讲述如何升级Cloudera Manager和CDH,通过本文档,您将学习到以下知识: 1.如何对Cloudera Manager进行停机升级 2.如何对CDH进行停机升级 3.如何在不影响集群作业的情况...

Hadoop实操
31分钟前
1
0
vue2中引用 better-scroll的方法

文章主要介绍了vue2中引用better-scroll和使用 better-scroll的方法,使用时有三个要点及注意事项在文中给大家详细介绍 ,需要的朋友可以参考下 使用时有三个要点: 一:html部分 <div class...

前端攻城老湿
41分钟前
1
0
浅谈教你如何掌握Linux系统

linux能做什么?相信绝大数人都有这样的疑问。可以玩吃鸡吗?可以玩lol吗? 如果你是以娱乐的名义来评价linux的可用性,对不起,linux可能不适合你,因为linux是一个工具,他是教你聪明的,不...

linuxprobe16
47分钟前
1
0
java中线程池的生命周期

线程池生命周期包括: RUNNING:接收新的任务并处理队列中的任务 SHUTDOWN:不接收新的任务,但是处理队列中的任务 STOP:不接收新的任务,不处理队列中的任务,同时中断处理中的任务 TIDYING:所...

小刀爱编程
55分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部