¿Qué es exactamente AOP?

Prefacio

Recordando que la primera vez que escuché estas tres letras fue cuando era estudiante de segundo año en la universidad, estaba confundido en ese momento, ahora que estoy en mi segundo año, lo pienso y lo reviso.

Solo recuerdo que en ese momento no entendía la programación orientada a objetos, y ahora me presentaron la programación orientada a aspectos, lo que me confundió por completo. . . .
Insertar descripción de la imagen aquí
Creo que todo el mundo está familiarizado con la programación orientada a objetos, así que echemos un vistazo a qué es la programación orientada a aspectos.

¿Qué significa programación orientada a aspectos?

No nos centraremos en la retórica oficial, centrémonos en la popular.

Imagine el siguiente escenario. Usted se hace cargo de un sistema de gestión de personal. Este proyecto no tiene ninguna gestión de permisos y la mayoría de las funciones se han completado. En este momento, la Parte A de repente tiene un nuevo requisito. Ahora espero que agregue el siguientes requisitos: La autoridad de la gestión de personal significa que los gerentes de departamento solo pueden gestionar el personal de sus propios departamentos y no pueden gestionar el personal de otros departamentos.

En este momento, puede pensar en agregar un marco de seguridad, pero pronto se dará por vencido porque hay demasiadas interfaces que requieren permisos y no puede cambiarlas una por una según los permisos del usuario para limitar los permisos de administración.

En este momento aparece el papel de aop,
Insertar descripción de la imagen aquí
entonces, ¿qué se puede hacer?

Generalmente colocamos todos los controladores que contienen interfaces en un paquete. En este momento, estamos pensando, ¿ podemos operar con la ID del empleado pasada antes de pasar la ID del empleado a la interfaz?

Es decir, después de que el front-end los pase, revisaremos estos ID nuevamente y eliminaremos los ID de los empleados que no tienen permiso para administrar. ¿Podemos eliminarlos?

Afortunadamente, puedes

Podemos pensar que existe un plano entre el cliente y la interfaz de llamada, en este plano podemos procesar los parámetros de id que se pasarán a la interfaz y eliminar directamente aquellos ids que no tienen permiso para operar. Este aspecto puede considerarse un aspecto, y la programación orientada a aspectos es así.

Este es solo un ejemplo, en este caso no solo existen aspectos, sino que también entre objetos y objetos, entre métodos y métodos, etc., se puede considerar como un aspecto.

Entonces, ¿cómo implementar la programación orientada a aspectos?

Aquí usamos anotaciones para lograr

La primera es ¿cómo monitoreamos esta superficie?
Primero echemos un vistazo a la interfaz.

package com.xiaow.springsecuriydemo.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaow.springsecuriydemo.entity.Person;
import com.xiaow.springsecuriydemo.service.PersonService;
import com.xiaow.springsecuriydemo.vo.Result;
import io.jsonwebtoken.lang.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author xiaow
 * @since 2023-09-01
 */
@RestController
@RequestMapping("/person")
public class PersonController {
    
    
    @Autowired
    PersonService personService;

    @GetMapping("getPersons")
    public Result getPersons(int adminid, int[] personids) {
    
    
        LambdaQueryWrapper<Person> personLambdaQueryWrapper = new LambdaQueryWrapper<>();
        List list1 = Collections.arrayToList(personids);
        personLambdaQueryWrapper.in(Person::getId, list1);
        List<Person> list = personService.list(personLambdaQueryWrapper);
        return Result.succ(list);
    }

}

La operación mplus aquí se deja para que todos la escriban.

Aprendamos a escribir Aspecto

@Before(value = "execution(* com.xiaow.springsecuriydemo.controller.*.*(..))")

Antes significa que operamos la interfaz antes de ejecutarla. com.xiaow.springsecuriydemo.controller es el paquete donde almacenamos el controlador. El primer * después representa cualquier controlador y el segundo * () es cualquier método.

El significado es realizar un paso de procesamiento antes de que se ejecuten todas las interfaces en com.xiaow.springsecuriydemo.controller. Entonces, ¿qué se debe procesar?

Por supuesto, la identificación del empleado pasada se procesa reemplazando las identificaciones que no están autorizadas para ser procesadas. Aquí usamos -1 en su lugar, porque la identificación de -1 no apuntará a ninguna información del empleado.

Echa un vistazo al código completo.

package com.xiaow.springsecuriydemo.aop.advice;

import com.xiaow.springsecuriydemo.aop.annotation.ArgsAnnotation;
import com.xiaow.springsecuriydemo.aop.annotation.ArraysAnnotation;
import com.xiaow.springsecuriydemo.entity.Admin;
import com.xiaow.springsecuriydemo.entity.Person;
import com.xiaow.springsecuriydemo.service.AdminService;
import com.xiaow.springsecuriydemo.service.PersonService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

@Aspect
@Component
public class PersonAdvice {
    
    
    @Autowired
    AdminService adminService;
    @Autowired
    PersonService personService;

    //  在进入接口之前执行
    @Before(value = "execution(* com.xiaow.springsecuriydemo.controller.*.*(..))")
    public void before(JoinPoint joinPoint) throws IllegalAccessException, NoSuchFieldException {
    
    
        final Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        // 获取参数的名字
        final String[] names = methodSignature.getParameterNames();
        // 获取参数的值
        final Object[] args = joinPoint.getArgs();
        int admin_index = -1;
        int personid_index = -1;
        // 获取到adminid和personids的下标位置
        for (int i = 0; i < names.length; i++) {
    
    
            if (names[i].equals("adminid")) {
    
    
                admin_index = i;
            }
            if (names[i].equals("personids")) {
    
    
                personid_index = i;
            }
        }

        Integer adminid = (Integer) args[admin_index];
        int [] personid = (int[]) args[personid_index];
        Admin byId = adminService.getById(adminid);
        if (byId != null) {
    
    
            Integer deptid = byId.getDeptid();
            List<Person> byDeptIdAndPersonids = personService.getByDeptIdAndPersonids(deptid, personid);
            int[] personids = (int[]) args[personid_index];
            for (Integer i = 0; i < personids.length; i++) {
    
    
                boolean flag = false;
                for (Person byDeptIdAndPersonid : byDeptIdAndPersonids) {
    
    
                    if (personids[i] == byDeptIdAndPersonid.getId())
                        flag = true;
                }
//              若不在有权限的id中,则直接设置为-1
                if (!flag)
                    Array.setInt(personid, i, -1);
            }

        }


    }

    // 在接口执行完毕后执行
    @After(value = "execution(* com.xiaow.springsecuriydemo.controller.*.*(..))")
    public void after() {
    
    
        System.out.println("after");
    }


}

Logros

De esta manera, logramos el control de permisos sin modificar la interfaz original, como se muestra a continuación.

Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_43627076/article/details/132628188
Recomendado
Clasificación