美文网首页
SpringAOP-3

SpringAOP-3

作者: 煗NUAN | 来源:发表于2020-02-28 22:12 被阅读0次

SpringAOP实现代理-5(通知)

  • 通知分类

    • 前置通知 before : 在业务方法执行之前执行, 前置通知不会影响连接点的执行,除非此处抛出异常。
    • 后置通知 after : 在业务方法执行之后调用的通知,无论方法执行是否成功.
    • 带返回值通知 after-returning : 可以拿到方法的返回值,仅当方法成功完成后执行的通知, 如果连接点抛出异常,则不会执行。
    • 异常通知 after-throwing : 在方法抛出异常退出时执行的通知,若不抛出异常,则不执行,可以捕获业务方法中的异常对象
    • 环绕通知 around : 同时在业务方法的前后执行
  • 顺序

    • 若是按照xml文件中通知按照before,after,around,after-returning,after-throwing的顺序书写的话

      • 异常通知不执行的情况下 :

        before>around before>业务方法 >after returning > around after >after

      • 异常通知执行的情况下 :

        before>around before>业务方法 >after throwing > after

    • 使用注解的话是环绕通知proceed方法之前部分先执行,使用xml配置的话取决于aop:before和aop:around的配置顺序

  • 目标类UserServiceImpl.java已实现接口

public class UserServiceImpl implements UserService {

    @Override
    public List getUser() {
        System.out.println("getUser");
        return null;
    }

    @Override
    public boolean saveUser(Object user) {
        System.out.println("saveUser");
        return false;
    }

    @Override
    public boolean deleteUser(int userId) {
        System.out.println("deleteUser");
        return false;
    }

    @Override
    public boolean updataUser(Object user) {
        System.out.println("updataUser");
        return false;
    }
}
  • 定义切面类 Aspect.java
  • JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
    • getSignature();获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
    • getArgs();获取传入目标方法的参数对象
    • getTarget();获取被代理的对象
    • getThis();获取代理对象
  • 环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别.
public class Aspect {

    //前置通知
    public void before(JoinPoint jp){
        //JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
        System.out.println("getTarget"+jp.getTarget());
        System.out.println("getArgs"+ Arrays.toString(jp.getArgs()));

        System.out.println("before");
    }
    //后置通知
    public void after(){
        System.out.println("after");
    }
    //环绕通知
    public Object aroundTest(ProceedingJoinPoint pjp){   //环绕通知要有返回内容
        //环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。
        try {
            System.out.println("around before");

            Object obj = pjp.proceed();

            System.out.println("around after");

            return obj;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    //带返回值的通知 ,配置文件的xml中,returning的属性值必须和返回值obj相同
    public void returnTest(JoinPoint jp ,Object obj){
        System.out.println("after returning");
        System.out.println("after-returning的返回值: "+obj);
    }

    //带异常的通知,若是无异常,则不执行
    public void throwsTest(JoinPoint jp,Throwable e){
        System.out.println("after throwing");
        System.out.println("after throwing打印异常信息: "+e.getMessage());
    }
}
  • 代理的.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--创建目标类的实现-->
    <bean id="us" class="com.aop.aop5.UserServiceImpl" />
    <!--创建切面类-->
    <bean id="asp" class="com.aop.aop5.Aspect" />

    <!--proxy-target-class的属性设置成true,强制使用cglib方式实现代理对象-->
    <aop:config proxy-target-class="true">
        <aop:aspect ref="asp">
            <!--切点-->
            <aop:pointcut id="pt" expression="execution(* com.aop.aop5.*.*(..))"/>

            <aop:before method="before" pointcut-ref="pt" />  <!--前置通知-->
            <aop:after method="after" pointcut-ref="pt" />  <!--后置通知-->
            <aop:around method="aroundTest" pointcut-ref="pt" />    <!--环绕通知-->
            <aop:after-returning method="returnTest" pointcut-ref="pt" returning="obj" />
            <!--返回通知需要有返回的obj,需要returning的属性值,且属性值与代理类的参数相同-->
            <aop:after-throwing method="throwsTest" pointcut-ref="pt" throwing="e" />
            <!--异常通知,需要throwing的属性值,且属性值与代理类的参数名相同-->
        </aop:aspect>
    </aop:config>
</beans>
  • 单元测试AOPTest.java
public class AOPTest5 {

    @Test
    public void UserService(){
        ApplicationContext ac=new ClassPathXmlApplicationContext("aop5/beans.xml");

        UserService userService=ac.getBean("us", UserService.class);

        userService.getUser();
        userService.saveUser(new Object());
        userService.deleteUser(3);
        userService.updataUser(new Object());
    }
}

相关文章

  • SpringAOP-3

    SpringAOP实现代理-5(通知) 通知分类前置通知 before : 在业务方法执行之前执行, 前置通知不会...

网友评论

      本文标题:SpringAOP-3

      本文链接:https://www.haomeiwen.com/subject/yxqdhhtx.html