Spring:AOP(xml形式的环绕通知)AOP概念:
AOP的作⽤以及优势
AOP的相关术语
基于XML的AOP配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance"
xmlns:aop="/schema/aop"
xsi:schemaLocation="/schema/beans
/schema/beans/spring-beans.xsd
/schema/aop
/schema/aop/spring-aop.xsd">
View Code
spring中基于XML的AOP配置步骤
1、把通知Bean也交给spring来管理
2、使⽤aop:config标签表明开始AOP的配置
3、使⽤aop:aspect标签表明配置切⾯
id属性:是给切⾯提供⼀个唯⼀标识
ref属性:是指定通知类bean的Id。
4、在aop:aspect标签的内部使⽤对应标签来配置通知的类型
我们现在⽰例是让printLog⽅法在切⼊点⽅法执⾏之前之前:所以是前置通知 aop:before:表⽰配置前置通知
method属性:⽤于指定Logger类中哪个⽅法是前置通知
pointcut属性:⽤于指定切⼊点表达式,
该表达式的含义指的是对业务层中哪些⽅法增强
切⼊点表达式的写法:
关键字:execution(表达式)
表达式:
访问修饰符返回值包名.包名.包名...类名.⽅法名(参数列表)
标准的表达式写法:
public void com.itheima.service.impl.AccountServiceImpl.saveAccount()访问修饰符可以省略
void com.itheima.service.impl.AccountServiceImpl.saveAccount()返回值可以使⽤通配符,表⽰任意返回值
* com.itheima.service.impl.AccountServiceImpl.saveAccount()包名可以使⽤通配符,表⽰任意包。但是有⼏级包,就需要写⼏个*.
* *.*.*.*.AccountServiceImpl.saveAccount())
包名可以使⽤..表⽰当前包及其⼦包
* *..AccountServiceImpl.saveAccount()
类名和⽅法名都可以使⽤*来实现通配
* *..*.*()
参数列表:
可以直接写数据类型:
基本类型直接写名称 int
引⽤类型写包名.类名的⽅式 java.lang.String
可以使⽤通配符表⽰任意类型,但是必须有参数
可以使⽤..表⽰有⽆参数均可,有参数可以是任意类型
全通配写法:
* *..*.*(..):这样的*(..)就代表这个类⾥的所有的⽅法都是被增强的实际开发中切⼊点表达式的通常写法:
切到业务层实现类下的所有⽅法
* com.itheima.service.impl.*.*(..)
如上图所⽰:使⽤AOP的配置让AccountServiceImpl执⾏之前先执⾏Logger来中的printLog⽅法
基于XML的环绕通知
在配置⽂件加上
<!-- 配置环绕通知详细的注释请看Logger类中-->
<aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around>
环绕通知
问题:
当我们配置了环绕通知之后,切⼊点⽅法没有执⾏,⽽通知⽅法执⾏了。
分析:
通过对⽐动态代理中的环绕通知代码,发现动态代理的环绕通知有明确的切⼊点⽅法调⽤,⽽我们的代码中没有。
解决:
Spring框架为我们提供了⼀个接⼝:ProceedingJoinPoint。该接⼝有⼀个⽅法proceed(),此⽅法就相当于明确调⽤切⼊点⽅法。
该接⼝可以作为环绕通知的⽅法参数,在程序执⾏时,spring框架会为我们提供该接⼝的实现类供我们使⽤。
spring中的环绕通知:
它是spring框架为我们提供的⼀种可以在代码中⼿动控制增强⽅法何时执⾏的⽅式。
spring framework和spring的关系在配置⽂件中配置切⼊点以及环绕通知
如图所⽰::环绕通知的代码:
结果显⽰如下:
除此之外我们还有其他的配置⽅式:
在spring的XML⽂件中
<!-- 配置srping的Ioc,把service对象配置进来-->
<bean id="accountService"class="com.itheima.service.impl.AccountServiceImpl"></bean>
<!-- 配置Logger类 -->
<bean id="logger"class="com.itheima.utils.Logger"></bean>
<!--配置AOP-->
<aop:config>
<!-- 配置切⼊点表达式 id属性⽤于指定表达式的唯⼀标识。expression属性⽤于指定表达式内容此标签写在aop:aspect标签内部只能当前切⾯使⽤。
它还可以写在aop:aspect外⾯,此时就变成了所有切⾯可⽤
-->
<aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut> <!--配置切⾯ -->
<aop:aspect id="logAdvice"ref="logger">
<!-- 配置前置通知:在切⼊点⽅法执⾏之前执⾏-->
<aop:before method="beforePrintLog" pointcut-ref="pt1" ></aop:before>
<!-- 配置后置通知:在切⼊点⽅法正常执⾏之后值。它和异常通知永远只能执⾏⼀个-->
<aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning> <!-- 配置异常通知:在切⼊点⽅法执⾏产⽣异常之后执⾏。它和后置通知永远只能执⾏⼀个--> <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing> <!-- 配置最终通知:⽆论切⼊点⽅法是否正常执⾏它都会在其后⾯执⾏-->
<aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>
</aop:aspect>
</aop:config>
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论