AOP拦截运用

AOP是Aspect Oriented Programming,即面向切面编程。

什么是AOP?

我们先回顾一下OOP:Object Oriented Programming,OOP作为面向对象编程的模式,获得了巨大的成功,OOP的主要功能是数据封装、继承和多态。
而AOP是一种新的编程方式,它和OOP不同,OOP把系统看作多个对象的交互,AOP把系统分解为不同的关注点,或者称之为切面(Aspect)。

AOP原理

如何把切面织入到核心逻辑中?这正是AOP需要解决的问题。换句话说,如果客户端获得了BookService的引用,当调用bookService.createBook()时,如何对调用方法进行拦截,并在拦截前后进行安全检查、日志、事务等处理,就相当于完成了所有业务功能。
在Java平台上,对于AOP的织入,有3种方式:

  1. 编译期:在编译时,由编译器把切面调用编译进字节码,这种方式需要定义新的关键字并扩展编译器,AspectJ就扩展了Java编译器,使用关键字aspect来实现织入;
  2. 类加载器:在目标类被装载到JVM时,通过一个特殊的类加载器,对目标类的字节码重新“增强”;
  3. 运行期:目标对象和切面都是普通Java类,通过JVM的动态代理功能或者第三方库实现运行期动态织入。

最简单的方式是第三种,Spring的AOP实现就是基于JVM的动态代理。由于JVM的动态代理要求必须实现接口,如果一个普通类没有业务接口,就需要通过CGLIB或者Javassist这些第三方库实现。
AOP技术看上去比较神秘,但实际上,它本质就是一个动态代理,让我们把一些常用功能如权限检查、日志、事务等,从每个业务方法中剥离出来。
需要特别指出的是,AOP对于解决特定问题,例如事务管理非常有用,这是因为分散在各处的事务代码几乎是完全相同的,并且它们需要的参数(JDBC的Connection)也是固定的。另一些特定问题,如日志,就不那么容易实现,因为日志虽然简单,但打印日志的时候,经常需要捕获局部变量,如果使用AOP实现日志,我们只能输出固定格式的日志,因此,使用AOP时,必须适合特定的场景。

AOP实例

某大学城区为严格执行防疫安全登记,对不同的区域入口实行健康码登记,进入校区,若健康码为绿色(以字符Y表示),学生信息方可提交健康系统;若健康码为非绿色(以字符N表示),学生信息不能提交健康系统。

文件结构:

在这里插入图片描述

数据库结构:

在这里插入图片描述

具体代码:

当工作人员发送请求/login,录入以下表格信息
在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>学生健康信息录入</h1>
    <form th:action="@{/add}" method="post">
        <tr>
            <td>用户编号</td>
            <td><input type="text" name="uid" id="uid"/></td>
        </tr>
        <br>
        <tr>
            <td>姓名</td>
            <td><input type="text" name="uname" id="uname"/></td>

            <td>年龄</td>
            <td><input type="text" name="age" id="age"/></td>

            <td>区域编号</td>
            <td><input type="text" name="area_no" id="area_no"/></td>
        </tr>
        <a th:href="@{/add}"><button>提交</button></a>
    </form>

</body>
</html>

当点击提交按钮时,由于学生健康码是现场查阅,设计一个AOP,确认学生的健康码状态,由工作人员现场手工录入:绿码用y表示,非绿码用n表示。
在WebControllerApp中注入AOP对获取信息进行拦截:

@Before("executeService()")
    public void dobeforeAdvice(JoinPoint joinPoint) {
        //获取ReqAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        Enumeration<String> enumeration = request.getParameterNames();
        Map<String, String> parameterMap = Maps.newHashMap();
        while (enumeration.hasMoreElements()) {
            String paramname = enumeration.nextElement();
            parameterMap.put(paramname, request.getParameter(paramname));
        }

        String per = JSON.toJSONString(parameterMap);
        System.out.println("健康码y/n");
        System.out.println(per);

        Scanner scanner = new Scanner(System.in);
        String jkm = scanner.nextLine();
        session.setAttribute("jkm",jkm);

    }

拦截过后对健康码颜色进行y/n判断

@Controller
public class IndexController {

    @Autowired
    private PersonService personService;

    @RequestMapping(value = "/index.html")
    public String toAdd() {
        return "index";
    }

    //添加
    @RequestMapping("/add")
    public String doAdd(Person person,
                      @RequestParam("uid") Integer uid,
                      @RequestParam("uname") String uname,
                      @RequestParam("age") Integer age,
                      @RequestParam("area_no") Integer area_no,
                      Model model,
                      HttpSession session){

        Object jkm = session.getAttribute("jkm");
        String a = (String) jkm;

        if (a.equals("y")) {

            session.setAttribute("uId",uid);
            session.setAttribute("uName",uname);
            session.setAttribute("age",age);
            session.setAttribute("jkm",jkm);
            session.setAttribute("areaNo",area_no);
            personService.add(person);

            System.out.println("AOP拦截成功");
            return "redirect:/reget.html";

        } else {

            System.out.println("AOP拦截成功");
            return "redirect:/error.html";
        }
    }

对健康码颜色进行判断。绿色则为y,拦截通过并写入数据库。
在这里插入图片描述在这里插入图片描述
红黄则为n,对信息进行拦截,不写入数据库,同时提示核酸不通过,不进行放行。
在这里插入图片描述在这里插入图片描述

项目下载:
链接:https://pan.baidu.com/s/1F8-Gdsfh6fi2uLG0fldiZQ
提取码:jgyy

AOP优点

在AOP中类与切面关系:
在这里插入图片描述

从可以看出,通过Aspect(切面)分别在Class1和Class2的方法中加入了事务、日志、权限和异常等功能。
AOP的使用,使开发人员在编写业务逻辑时可以专心于核心业务,而不用过多的关注于其他业务逻辑的实现,这不但提高了开发效率,而且增强了代码的可维护性。
目前最流行的AOP框架有两个,分别为Spring AOP和AspectJ。Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类织入增强的代码。AspectJ是一个基于Java语言的AOP框架,从Spring2.0开始,Spring AOP引入了对AspectJ的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值