AOP的具体实践-简化结果返回的处理

原因:

  以前学习Spring的时候着重学习过AOP概念,但是一直也没有用上,唯一碰到过的就是Spring内置的事务管理。现在碰到过一些结果后面的操作适合用到,所以这里就拿出来用一下,并且复习一下落下的知识。

概念:

  基本概念这个博主解释的比较清楚,如果有不懂的可以去看一下。https://blog.csdn.net/csh624366188/article/details/7651702

  在我的认识里,如果某些方法重复性特别高,可以抽象出来形成一个切面,则可以使用AOP来简化代码,即在方法的某些部分动态的添加某些方法,起到简化代码的作用。

具体需求:

  项目的Service层通过webService获取到数据,需要对获取到的数据进行判断处理,对其异常信息作出记录和抛出异常。同时还需要在进入和结束方法的时候进行日志记录。

知识点:

配置方法:

  在这里使用的是注解的方式来配置的AOP,首先,要保证项目中除了Spring基本包以外还包含aopalliance-1.0.jar,aspectjrt-1.8.7.jar,aspectjweaver-1.8.7.jar,cglib-nodep-3.2.4.jar这四个jar包,这里将其打包放到百度云,如果有需要的可以去下载。链接:https://pan.baidu.com/s/1rDqLY1lnWdiahVkLcZd_bw 密码:0uea

  Spring配置添加如下, 添加<aop:aspectj-autoproxy />需要添加Spring的头部内容

  注意aop不能添加到static方法上面。

    <aop:aspectj-autoproxy />  // 扫描AOP
    <!-- 这里配置后就不用再使用bean标签配置bean了 -->
    <context:annotation-config></context:annotation-config>
    <!-- 去哪个包扫描生成bean -->
    <context:component-scan base-package="com.dazhong.jnfy.alipay.action" />

  首选建立切面类:其中的afterReturning就是主要的切面方法,用于对返回值进行判断并且进行对应的操作,这样可以不用再每个方法中都写一次。

  @Pointcut("execution(* com.dazhong.jnfy.alipay.service.impl.*.*(..))"):表示AOP会代理那些方法,这里则表示com.dazhong.jnfy.alipay.service.impl包下面所有方法都会执行
  @After("picter()"):后置通知
  @Before("picter()"):前置通知
package com.dazhong.jnfy.alipay.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.json.JSONObject;
import org.springframework.stereotype.Component;

import com.dazhong.jnfy.alipay.exception.ConnectionException;
import com.dazhong.jnfy.alipay.exception.ResultErrorException;
import com.dazhong.utils.LogUtil;

@Component
@Aspect
public class ServiceAop {

    @Pointcut("execution(* com.dazhong.jnfy.alipay.service.impl.*.*(..))")
    public void picter() {
    }

    /**
    * @Description: 对返回值进行处理
    * @param point
    * @param rvt
    * @throws ResultErrorException 
    */
    @AfterReturning(returning = "rvt", pointcut = "execution(* com.dazhong.jnfy.alipay.service.impl.*.*(..))")
    public void afterReturning(JoinPoint point, Object rvt) throws Exception {  // Object rvt则是方法返回值,这里变量名称要和注解retruning值相同
        String[] strs = point.getSignature().getDeclaringTypeName().split("\\.");
        String fullname = strs[strs.length - 1] + "." + point.getSignature().getName();

        JSONObject root = (JSONObject) rvt;

        if (rvt == null) {
            throw new ConnectionException("WebService连接失败" + fullname);
        } else if (!root.has("resultCode") || !root.get("resultCode").toString().equals("0")) {
            // 返回数据异常
            throw new ResultErrorException("WebService 返回结果异常:" + root.toString());
        }
    }

    @Before("picter()")
    public void before(JoinPoint point) {
        String[] strs = point.getSignature().getDeclaringTypeName().split("\\.");
        String fullname = strs[strs.length - 1] + "." + point.getSignature().getName();
        LogUtil.info("进入方法:" + fullname);
    }

    @After("picter()")
    public void after(JoinPoint point) {
        String[] strs = point.getSignature().getDeclaringTypeName().split("\\.");
        String fullname = strs[strs.length - 1] + "." + point.getSignature().getName();
        LogUtil.info("方法结束:" + fullname);
    }

}

  获取参数/方法名:

    如果需要获取目标方法的参数/名字,则需要在切面的方法中添加变量 JoinPoint point,通过这个对象来进行获取。

     String allname = point.getSignature().getDeclaringTypeName();  // 获取整个路径 包名+类名
     System.out.println(allname);
     String[] split = allname.split("\\.");
     System.out.println("目标方法:" + split[split.length - 1] + "." + point.getSignature().getName());  // point.getSignature().getName() 获取方法名
     System.out.println("@Before:参数为:" + Arrays.toString(point.getArgs()));  // 获取目标方法的参数 point.getArgs()

结果: 红框内容就是AOP自动添加的。

剩余代码:

  目标方法:

    public JSONObject test() throws Exception{
        System.out.println("目标方法执行");
        JSONObject js = new JSONObject();
        js.put("resultCode", "-1");
        return js;
    }

  测试方法:

    public static void main(String[] args) {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
        ReserveServiceImpl b = (ReserveServiceImpl) appCtx.getBean("reserveServiceImpl");
        JSONObject js = new JSONObject();
        js.put("s", "111");
        try {
            //JSONObject allDept = b.getDocterByTimeAndDept("YYKS002", "20180711");
            b.test();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏步履前行

Spring @PostConstruct 、@Autowired和Construct 顺序

今天修bug的时候发现了@PostConstruct 注解,之前一直没注意到,今天正好学习了下,就来总结一波。

10.7K30
来自专栏Jed的技术阶梯

Java设计模式之模板方法模式

假设我们现在要造一批悍马汽车,悍马汽车有两个系列H1和H2,首先不考虑任何设计模式,看看设计的类图:

12830
来自专栏JMCui

再学习之Spring(面向切面编程).

一、概念 1、理论     把横切关注点和业务逻辑相分离是面向切面编程所要解决的问题。如果要重用通用功能的话,最常见的面向对象技术是继承(inheritance...

28450
来自专栏xingoo, 一个梦想做发明家的程序员

【Spring实战】—— 9 AOP环绕通知

假如有这么一个场景,需要统计某个方法执行的时间,如何做呢?   典型的会想到在方法执行前记录时间,方法执行后再次记录,得出运行的时间。 如果采用Sp...

24250
来自专栏精讲JAVA

Spring AOP 的实现原理

AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点...

50370
来自专栏一英里广度一英寸深度的学习

Spring 基础

interface声明接口,接口中的函数不用public/private,但是要匹配参数和异常。

10710
来自专栏xingoo, 一个梦想做发明家的程序员

【Spring实战】—— 5 设值注入

本篇主要讲解了Spring的最常用的功能——依赖注入。 注入的方式,是使用Getter Setter注入,平时大多的编程也都是使用这种方法。   举个简...

23270
来自专栏大内老A

.NET Core采用的全新配置系统[9]: 为什么针对XML的支持不够好?如何改进?

物理文件是我们最常用到的原始配置的载体,最佳的配置文件格式主要由三种,它们分别是JSON、XML和INI,对应的配置源类型分别是JsonConfiguratio...

20250
来自专栏javathings

Spring 中 AOP 的实现

AOP 称为面向切面编程,在程序开发中,AOP 技术可以在不改变原有方法代码的情况下,把逻辑直接插入到方法上。Spring AOP 的大致原理主要依靠的是动态代...

12140
来自专栏黑泽君的专栏

day34_Spring学习笔记_02

1.2.2.2、切面类   MyAspect.java的代码同上 1.2.1.2、切面类 代码,这里不再赘述!

9740

扫码关注云+社区

领取腾讯云代金券