Spring-AOP
Posted 张坤
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring-AOP相关的知识,希望对你有一定的参考价值。
AOP(Aspect Oriented Programming):面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是Spring框架中的一个重要内容。
举个栗子:
有A,B,C三个方法,在调用每个方法之前,打印一个日志:方法被开始调用了!在调用每个方法之后,也要求打印日志:某个方法被调用完了!如果在每一个方法的开始和结尾都添加日志打印,方法多了就会有很多重复的代码,所以把打印日志这个功能封装一下,然后让它能在指定的地方(比如执行方法前,或者执行方法后)自动的去调用的话,业务功能代码中就不会掺杂其他的代码,所以AOP就是做了这一类的工作,比如,日志输出,事务控制,异常的处理等。。
如果把AOP当做成给我们写的“业务功能”增添一些特效,就会有这么几个问题:
1.我们要制作哪些特效
2.这些特效使用在什么地方
3.这些特效什么时候来使用
下面我们来说一下AOP的一些术语(一下看不懂不要紧,慢慢理解)
1.通知(Advice)
所谓通知指的是拦截到连接点之后要执行的代码,通常分为前置 后置 异常 最终 环绕通知五类
2.连接点(JoinPoint)
这个更好解释了,就是spring允许你使用通知的地方,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点
3.切入点(Pointcut)
在连接点的基础上定义切入点,一个类里,有15个方法,就有几十个连接点了,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),只在调用部分方法之前,之后或者抛出异常时通知,那么就用 切点来定义这几个方法,让切点来筛选连接点,选中想要的方法。
4.切面(Aspect)
切面是通知和切入点的结合。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。
5.引入(introduction)
允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗
6.目标(target)
引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面。而自己专注于业务本身的逻辑。
7.代理(proxy)
怎么实现整套aop机制的,都是通过代理,这个一会给细说。
8.织入(weaving)
把切面应用到目标对象来创建新的代理对象的过程。有3种方式,spring采用的是运行时,为什么是运行时,后面解释。
关键就是:切点定义了哪些连接点会得到通知
下面是XML文件和测试类代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--配置扫描包-->
<context:component-scan base-package="com.mx.demo"/>
<!--配置通知对象-->
<bean id="log" class="com.mx.demo.LogAdvice"/>
<!--配置AOP-->
<aop:config>
<!--配置连接点,expression用于指定哪些类的哪些方法需要被拦截 -->
<!--第一个*代表任意的返回值类型-->
<!--第二个*ServiceImpl代表匹配ServiceImpl结尾的所有类-->
<!--第三个*代表类中所有的方法-->
<!--(..)代表方法任意的参数-->
<aop:pointcut id="pointcut1" expression="execution(* com.mx.demo.*ServiceImpl.add(..))"/>
<aop:pointcut id="pointcut2" expression="execution(* com.mx.demo.*ServiceImpl.update(..))"/>
<!--配置切面 ref引用通知对象-->
<aop:aspect id="aspect" ref="log">
<!--配置前置通知,method是通知类中的方法名 pointcut-ref是连接点-->
<aop:before method="beforeLog" pointcut-ref="pointcut1"/>
<aop:before method="beforeLog" pointcut-ref="pointcut2"/>
<aop:after method="afterLog" pointcut-ref="pointcut1"/>
<aop:around method="aroundLog" pointcut-ref="pointcut1"/>
<aop:after-throwing method="afterThrowLog" pointcut-ref="pointcut1"/>
<aop:after-returning method="afterReturnLog" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
</beans>
以上是关于Spring-AOP的主要内容,如果未能解决你的问题,请参考以下文章