Spring-AOP-xml

目录

AOP的相关概念

AOP入门案例(xml)

APOXML配置详解

aop:pointcut 标签

AOP五种通知类型

AOP通知的顺序

 AOP通知中获取方法返回值

 AOP中获取异常信息


AOP的相关概念

  • Joinpoint(连接点):就是方法
  • Pointcut(切入点):就是挖掉共性功能的方法
  • Advice(通知):就是共性功能,最终以一个方法的形式呈现
  • Aspect(切面):就是共性功能与挖的位置的对应关系
  • Target(目标对象):就是挖掉功能的方法对应的类产生的对象,这种对象是无法直接完成最终工作的
  • Weaving(织入):就是将挖掉的功能回填的动态过程
  • Proxy(代理):目标对象无法直接完成工作,需要对其进行功能回填,通过创建原始对象的代理对象实现
  • Introduction(引入/引介) :就是对原始对象无中生有的添加成员变量或成员方法

AOP入门案例(xml)

1、引入坐标

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

2、抽取通用代码

package com.jjs.config;
public class AOPAdvice {
    public void advice(){
    System.out.println("公共方法");
    }
}

3、编写配置文件

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.jjs.service.UserServiceImpl" ></bean>
    <bean  id="aop" class="com.jjs.config.AOPAdvice"></bean>
    <aop:config>
        <aop:pointcut id="pt" expression="execution(* *..*(..))"></aop:pointcut>
        <aop:aspect ref="aop">
                <aop:before method="advice" pointcut-ref="pt"></aop:before>
        </aop:aspect>
    </aop:config>
</beans>

APOXML配置详解

抽取的公共功能类

package com.jjs.config;
public class AOPAdvice {
    public void advice(){
        System.out.println("公共方法");
    }
}

AOP的XML配置,接下来的讲解都以这套为模板

<bean  id="aop" class="com.jjs.config.AOPAdvice"></bean>  抽取出来的公共功能,对应一个类
 <aop:config>
        <aop:pointcut id="pt" expression="execution(* *..*(..))"></aop:pointcut>
        <aop:aspect ref="aop">
                <aop:before method="advice" pointcut-ref="pt"></aop:before>
        </aop:aspect>
    </aop:config>
    
    </aop:config>

aop:config 标签

一组aop:config代表一套AOP,可以设置多套 

<beans>
    <aop:config>……</aop:config>
    <aop:config>……</aop:config>
</beans>

aop:aspect 标签 

设置具体(位置以及内容)的切入点,例如在目标方法的前面通知还是在目标方法的后面通知,以及通知的内容(方法)

<aop:aspect ref="aop"> 公共功能类对应的beanID
    <aop:before method="advice" pointcut-ref="pt"></aop:before>
</aop:aspect>

aop:pointcut 标签

设置切入的时机(当直接expression表达式中所涉及的方法就会开始通知)

 <aop:pointcut id="pointcutId" expression="execution(* *..*(..))/>

excution的表达式

execution(访问修饰符  返回值  包名.类名.方法名(参数)异常名)

访问修饰符:方法的访问控制权限修饰符  可省略

类名:方法所在的类(此处可以配置接口名称)

异常:方法定义中指定抛出的异常

示例:

execution(* *(..))
execution(* *..*(..))
execution(* *..*.*(..))
execution(public * *..*.*(..))
execution(public int *..*.*(..))
execution(public void *..*.*(..))
execution(public void com..*.*(..)) 
execution(public void com..service.*.*(..))
execution(public void com.jjs.service.*.*(..))
execution(public void com.jjs.service.User*.*(..))
execution(public void com.jjs.service.*Service.*(..))
execution(public void com.jjs.service.UserService.*(..))
execution(public User com.jjs.service.UserService.find*(..))
execution(public User com.jjs.service.UserService.*Id(..))
execution(public User com.jjs.service.UserService.findById(..))
execution(public User com.jjs.service.UserService.findById(int))
execution(public User com.jjs.service.UserService.findById(int,int))
execution(public User com.jjs.service.UserService.findById(int,*))
execution(public User com.jjs.service.UserService.findById(*,int))
execution(public User com.jjs.service.UserService.findById())
execution(List com.jjs.service.*Service+.findAll(..))

通配符

  • *:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

    execution(public * com.jjs.*.UserService.find*(*))

匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法

  • .. :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

    execution(public User com..UserService.findById(..))

匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法

  • +:专用于匹配子类类型

    execution(* *..*Service+.*(..))

切入点表达式——逻辑运算符

  • && :连接两个切入点表达式,表示两个切入点表达式同时成立的匹配

  • || :连接两个切入点表达式,表示两个切入点表达式成立任意一个的匹配

  • ! :连接单个切入点表达式,表示该切入点表达式不成立的匹配

AOP五种通知类型

xml配置

 <bean id="userService" class="com.jjs.service.UserServiceImpl" ></bean>
    <bean  id="aop" class="com.jjs.config.AOPAdvice"></bean>
    <aop:config>
        <aop:pointcut id="pt" expression="execution(* *..*(..))"></aop:pointcut>
        <aop:aspect ref="aop">
                <!--<aop:before method="before" pointcut-ref="pt"></aop:before>-->
            <!--<aop:after method="after" pointcut-ref="pt"></aop:after>-->
            <!--<aop:after-returning method="after_eturning" pointcut-ref="pt"></aop:after-returning>-->
            <!--<aop:after-throwing method="after_throwing" pointcut-ref="pt"></aop:after-throwing>-->
            <aop:around method="around" pointcut-ref="pt"></aop:around>
        </aop:aspect>
    </aop:config>

通知内容:

package com.jjs.config;
import org.aspectj.lang.ProceedingJoinPoint;
public class AOPAdvice {
    public void before(){
        System.out.println("前置通知");
    }
    public void after(){
        System.out.println("后置通知");
    }
    public void after_eturning(){
        System.out.println("返回后通知");
    }
    public void after_throwing(){
        System.out.println("抛出异常后通知");
    }
    public Object around(ProceedingJoinPoint pdj) throws Throwable {
        System.out.println("环绕前通知");
        Object proceed = pdj.proceed();
        System.out.println("环绕后通知");
        return proceed;
    }
}

前置通知:

<aop:before method="before" pointcut-ref="pt"></aop:before>

后置通知:

无论是否正常执行,在掉用方法完毕后都会执行后置通知

<aop:after method="after" pointcut-ref="pt"></aop:after>

返回后通知:

只有方法内正常运行、无异常才会执行返回后通知

<aop:after-returning method="after_eturning" pointcut-ref="pt"></aop:after-returning>

出现异常后通知:

只有当方法内部出现了异常后才会通知   

<aop:after-throwing method="after_throwing" pointcut-ref="pt"></aop:after-throwing>

环绕通知:

该方法较为特殊,从上面的通知内容可以看的,环绕通知的通知内容必须要在第一个参数添加ProceedingJoinPoint,然后通过它调取proceed,相当于执行核心方法,不然的话就会忽略核心方法(特有方法,通知修饰的内容)

 <aop:around method="around" pointcut-ref="pt"></aop:around>

AOP通知的顺序

当多个同种通知类型同时出现的时候,会按照配置的顺序先后进行执行

例如我这里设置了3个前置通知

 然后在xml配置中配置的顺序为2、3、1

 看看执行的输出结果,会根据配置的顺序先后执行

当多个不同的通知类型同时出现,会根据功能然后根据配置的顺序先后执行

比如说,一个是前置通知,一个是后置通知,那肯定是先执行前置通知,等方法执行完后再执行后置通知。但是如果是一个环绕通知和一个前置通知同时出现,那么就根据谁先配置先执行谁,如果先配置前置通知,那么就会先执行前置通知完之后再执行环绕通知的前置通知。

 

 这时候看执行结果

 AOP通知中获取方法返回值

首先要先知道有哪些通知类型不可以获取方法返回值

  • 前置通知before不能获取方法返回值,因为方法还没执行
  • 后置通知after也不能获取方法返回值,因为后置通知不管是否出现异常都能执行,而在执行的时候也不知道会不会出现异常,所以干脆不获取返回值
  • 异常后通知after-throwing也不能获取返回值,都出现异常了何有返回值之说

除开三种,剩下的两种通知都可以获取方法返回值

after-returning获取返回值

首先要在通知内容参数加上返回值类型,如果不知道返回值类型就使用Object

 然后再xml配置中,通过returning来接收,参数写的正是java代码中的接收变量名。

环绕通知获取返回值的方法

通过调用proceedingJoinPoint 的proceed方法相当于执行了目标方法,然后Object接收返回值即可,但是要retrun出去,不然会报错

 AOP中获取异常信息

首先要先知道有哪些通知类型不可以获取异常信息

  • 前置通知before不能获取异常信息,因为方法还没执行
  • 后置通知after也不能获取异常信息,因为后置通知不管是否出现异常都能执行,而在执行的时候也不知道会不会出现异常,所以干脆不获取
  • 返回后通知after-returning是正常执行返回,肯定没有异常信息,所以也不行

除开三种,剩下的两种通知都可以获取方法返回值

抛出异常通知after-throwning获取异常信息

首先也是在通知方法的参数上加上一个参数用于接收异常

在xml中通过throwing来接收,参数写的正是java代码中的接收变量名。

环绕通知获取异常的方法

只需要在调用proceedingJoinPoint的proceed中处理异常即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值