"AOP se da cuenta del negocio de la caché de Redis"

AOP se da cuenta del negocio de almacenamiento en caché

Necesidades del negocio

  • 1 Utilice anotaciones personalizadas para representar métodos comerciales y el valor de retorno de la empresa se almacena en la memoria caché.

  • 2 Use AOP para interceptar anotaciones y use métodos de notificación envolvente para lograr negocios


Prepárate de antemano

1. Cree el archivo de configuración de Redis (prepare el nodo de Redis)

创建properties配置文件,里面存入Redis节点

Inserte la descripción de la imagen aquí

#准备redis的节点信息
redis.host=192.168.126.129
redis.port=6379

2. Cree una clase de configuración de Redis (el nodo se entrega al contenedor de primavera para su administración)

创建class类 里面导入配置文件存储的节点信息并且交给spring管理

Inserte la descripción de la imagen aquí

@Configuration //表示一个配置类 一一般会@bean的注解关联
@PropertySource("classpath:/redis.properties") //导入配置文件
public class redis {
    
    

    @Value("${redis.host}")
    private String host;
    @Value("${redis.port}")
    private Integer port;

    @Bean   //将方法的返回值结果,交给spring容器进行管理.
    public Jedis jedis(){
    
    
        return new Jedis(host, port);
    }
}

3. Cree una clase de herramienta Redis (utilizada para convertir objetos en formato JSON y convertir objetos a JSON)

把数据库的对象格式转换JSON格式存储缓存中,把缓存的JSON格式转换对象格式传入客户端

Inserte la descripción de la imagen aquí

public class RedisUtl {
    
    

    private static final ObjectMapper MAPPER=new ObjectMapper();
    //对象转json
    public static String toJSON(Object object) {
    
    
        try {
    
    
            return MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
    
    
            e.printStackTrace();
            throw new RuntimeException();
        }
    }
    //2.JSON转化为对象 要求用户传递什么类型就返回什么对象??
    public static <T> T toObject(String json,Class<T> target){
    
    
        try {
    
    
            return MAPPER.readValue(json, target);
        } catch (JsonProcessingException e) {
    
    
            e.printStackTrace();
            throw new RuntimeException();
        }
    }
}

Caso inicial

1. Crea anotaciones personalizadas

注解是接口,用来指定目标业务方法,并且拦截

Inserte la descripción de la imagen aquí

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisAopFind {
    
    
    String key();
    int seconds() default -1;
}

Notas utilizadas

@Target () ----- Esta anotación describe el alcance de uso de la anotación, dónde se utiliza esta anotación

ElementType ----- valor

MÉTODO ----- Esta anotación se utiliza para describir el método

@Retention () ----- El rol es definir cuánto tiempo se retienen las anotaciones anotadas por él

RetentionPolicy ----- valor

RUNTIME ----- las anotaciones no solo se guardan en el archivo de clase, sino que aún existen después de que jvm carga el archivo de clase

String key (); ---- definir el valor de la clave

int segundos () predeterminado -1; ---- tiempo de espera predeterminado -1 no es tiempo de espera predeterminado


2. Las anotaciones indican métodos comerciales

Inserte la descripción de la imagen aquí

  • Aquí está nuestra anotación personalizada

  • la clave es el nombre de nuestro método comercial

  • El método descrito en nuestra anotación personalizada se intercepta en AOP

3. AOP inicial

3.1 Cree una clase Java, lo que significa que la clase creada es una clase empresarial de Aop

Inserte la descripción de la imagen aquí

当前的类是处理AOP业务的类

@Component
@Aspect
public class RedisAOP {
    
    

    @Autowired
    private Jedis jedis;

}

@Component ----- Esta clase de descripción de anotación se entrega a la gestión de primavera

@Aspect ----- La clase descrita por esta anotación es una clase que representa AOP (Orientado a aspectos)

   @Autowired
    private Jedis jedis;

我们导入Redis的配置类


4. Estructura empresarial


@Component
@Aspect
public class RedisAOP {
    
    

    @Autowired
    private Jedis jedis;
    

    @Around("@annotation(redisAopFind)")
    public Object around(ProceedingJoinPoint joinPointm, RedisAopFind redisAopFind){
    
    
        Object result=null;
        String Key=redisAopFind.key();
        //动态获取方法的参数
        String args= Arrays.toString(joinPointm.getArgs());
        Key = Key + "::" + args;

        if (jedis.exists(Key)){
    
    
            String json=jedis.get(Key);
            //动态获取方法的类型
            MethodSignature methodSignature= (MethodSignature) joinPointm.getSignature();
            Class returnType = methodSignature.getReturnType();

            result = RedisUtl.toObject(json, returnType);
            System.out.println("AOP查询redis缓存");
        }else{
    
    
            try {
    
    
             result =joinPointm.proceed(); //执行下一个通知,执行目标方法

             String json=RedisUtl.toJSON(result);
             if (redisAopFind.seconds()>0){
    
    
                 jedis.setex(Key, redisAopFind.seconds(), json);
             }else {
    
    
                 jedis.set(Key, json);
             }
                System.out.println("AOP查询数据库");
            }catch (Throwable throwable) {
    
    
                throwable.printStackTrace();
            }
        }
        return result;
    }

}

El primer paso es interceptar el negocio y encapsular la CLAVE

 @Around("@annotation(redisAopFind)")
    public Object around(ProceedingJoinPoint joinPoint, RedisAopFind redisAopFind){
    
    
        Object result=null;
        String Key=redisAopFind.key();
        //动态获取方法的参数
        String args= Arrays.toString(joinPointm.getArgs());
        Key = Key + "::" + args;

En primer lugar, importo nuestra anotación personalizada @Around es la notificación envolvente, usamos la notificación envolvente para interceptar el método descrito por nuestra anotación personalizada y obtenemos el valor de retorno del método

  • JoinPoint: el método de punto de entrada, el objeto de la información del método de destino que se está ejecutando, el punto popular (interceptamos el administrador de métodos de destino)
  • redisAopFind-anotaciones personalizadas que creamos
  • redisAopFind.key (): obtiene la clave en la anotación personalizada, el valor de clave que asignamos cuando la anotación describe el método de destino
  • joinPointm.getArgs (): obtenga los parámetros en el método de destino, necesitamos la concatenación de cadenas, así que use el método tostring
Key = Key + "::" + args;
  • El valor de clave obtenido se empalma con los parámetros del método de destino para encapsular el valor de clave en redis

inmediato:

Nuestra LLAVE cambia y no puede usar una clave fija. Por lo tanto, si los parámetros están empalmados, los parámetros solicitados por el cliente no son los mismos, y nuestros valores clave también se cambian dinámicamente. Esto es fácil de distinguir, y los parámetros correspondientes también se utilizan al almacenar. Encapsulación

Verificación de segundo paso

1- El valor de KEY existe en Redis (obtén el valor en redis)

if (jedis.exists(Key)){
    
    
    String json=jedis.get(Key);
    //动态获取方法的类型
    MethodSignature methodSignature= (MethodSignature) joinPointm.getSignature();
    Class returnType = methodSignature.getReturnType();

    result = RedisUtl.toObject(json, returnType);
    System.out.println("AOP查询redis缓存");
}
  • Determine si existe actualmente nuestra CLAVE encapsulada en la caché de redis

  • Si existe, obtenga el valor de KEY

String json=jedis.get(Key);
  • joinPointm.getSignature () para obtener la firma del método de destino

    • Queremos asignar la firma del método de la clase principal de joinPointm para usar la razón.
    • El resultado impreso muestra la firma del método objetivo.

Inserte la descripción de la imagen aquí

 MethodSignature methodSignature= (MethodSignature) joinPointm.getSignature();
  • Obtenga dinámicamente el tipo de método de destino basado en la firma

  • getReturnType Obtiene el tipo de la firma del método de destino actual (es decir, el tipo de método de destino)

  • El resultado impreso muestra el tipo de método objetivo

Inserte la descripción de la imagen aquí

 Class returnType = methodSignature.getReturnType();

缓存中KEY的值转换成目标方法的类型,并返回

result = RedisUtl.toObject(json, returnType);

2- El valor de KEY no existe en redis (consulta la base de datos y guárdalo en la caché)

else{
    
    
    try {
    
    
     result =joinPointm.proceed(); //执行下一个通知,执行目标方法

     String json=RedisUtl.toJSON(result);
     if (redisAopFind.seconds()>0){
    
    
         jedis.setex(Key, redisAopFind.seconds(), json);
     }else {
    
    
         jedis.set(Key, json);
     }
        System.out.println("AOP查询数据库");
    }catch (Throwable throwable) {
    
    
        throwable.printStackTrace();
    }
}
  • Si no hay datos de consulta en redis, ejecute directamente el método de destino y consígalo en la base de datos

  • joinPointm.proceed (); ejecutar el método de destino

result =joinPointm.proceed(); 
  • El valor de retorno del método de destino que consulta la base de datos se convierte al tipo Json

String json=RedisUtl.toJSON(result);
  • En la actualidad, no hemos establecido el tiempo de espera. Si lo hacemos en el futuro, el tiempo de espera será mayor que 0. Luego, defina el tiempo de espera que establecemos al almacenar

  • Almacenar directamente si no hay tiempo de espera

if (redisAopFind.seconds()>0){
    
    
    jedis.setex(Key, redisAopFind.seconds(), json);
}else {
    
    
    jedis.set(Key, json);
}

Expandir

Cuando definimos anotaciones personalizadas, definimos el tiempo de espera predeterminado sin tiempo de espera, por lo que si definimos el tiempo de espera,
Inserte la descripción de la imagen aquí
agregue el tiempo de espera cuando la anotación personalizada describe el método


3. Finalización empresarial

devuelve resultado: devuelve el resultado de
Inserte la descripción de la imagen aquí
la consulta del cliente La primera consulta es la base de datos, la
segunda consulta es la caché

Supongo que te gusta

Origin blog.csdn.net/weixin_45103228/article/details/113773727
Recomendado
Clasificación