"AOP realiza negócios de cache Redis"

AOP realiza negócios de cache

Necessidades de negócios

  • 1 Use anotações personalizadas para representar métodos de negócios, e o valor de retorno do negócio é armazenado no cache

  • 2 Use AOP para interceptar anotações e usar métodos de notificação surround para fazer negócios


Prepare com antecedência

1. Crie o arquivo de configuração do Redis (prepare o nó do redis)

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

Insira a descrição da imagem aqui

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

2. Crie uma classe de configuração Redis (o nó é entregue ao contêiner de primavera para gerenciamento)

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

Insira a descrição da imagem aqui

@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. Crie uma classe de ferramenta Redis (usada para converter objetos em formato JSON e converter objetos em JSON)

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

Insira a descrição da imagem aqui

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. Crie anotações personalizadas

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

Insira a descrição da imagem aqui

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

Notas usadas

@Target () ----- Esta anotação descreve o escopo de uso da anotação, onde esta anotação é usada

ElementType ----- valor

MÉTODO ----- Esta anotação é usada para descrever o método

@Retention () ----- A função é definir por quanto tempo as anotações anotadas por ela são retidas

RetentionPolicy ----- valor

RUNTIME ----- as anotações não são apenas salvas no arquivo de classe, mas ainda existem após o jvm carregar o arquivo de classe

String key (); ---- define o valor da chave

segundos int () padrão -1; ---- tempo limite padrão -1 não é tempo limite por padrão


2. As anotações indicam métodos de negócios

Insira a descrição da imagem aqui

  • Aqui está nossa anotação personalizada

  • a chave é o nome do nosso método de negócios

  • O método descrito em nossa anotação personalizada é interceptado no AOP

3. AOP inicial

3.1 Crie uma classe Java, o que significa que a classe criada é uma classe de negócios de Aop

Insira a descrição da imagem aqui

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

@Component
@Aspect
public class RedisAOP {
    
    

    @Autowired
    private Jedis jedis;

}

@Component ----- Esta classe de descrição de anotação é entregue ao gerenciamento do Spring

@Aspect ----- A classe descrita por esta anotação é uma classe que representa AOP (Orientado a Aspectos)

   @Autowired
    private Jedis jedis;

我们导入Redis的配置类


4. Estrutura de negócios


@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;
    }

}

O primeiro passo é interceptar o negócio e encapsular a CHAVE

 @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;

Em primeiro lugar, eu importo nossa anotação personalizada @Around é a notificação surround, usamos a notificação surround para interceptar o método descrito por nossa anotação personalizada e obter o valor de retorno do método

  • JoinPoint - o método do ponto de entrada, o objeto da informação do método alvo sendo executado, o ponto popular (interceptamos o gerenciador do método alvo)
  • anotações personalizadas de redisAopFind que criamos
  • redisAopFind.key () - Obtenha a chave na anotação personalizada, o valor chave que atribuímos quando a anotação descreve o método de destino
  • joinPointm.getArgs () - Obtenha os parâmetros no método de destino, precisamos da concatenação de string, então use o método tostring
Key = Key + "::" + args;
  • O valor da chave obtido é combinado com os parâmetros do método de destino para encapsular o valor da chave no redis

incitar:

Nossa KEY muda e não pode usar uma chave fixa. Portanto, se os parâmetros forem combinados, os parâmetros solicitados pelo cliente não serão os mesmos e nossos valores-chave também serão alterados dinamicamente. Isso é fácil de distinguir, e os parâmetros correspondentes também são usados ​​ao armazenar.

Verificação da segunda etapa

1- O valor de KEY existe no Redis (obtenha o valor no 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 se há atualmente nossa CHAVE encapsulada no cache do Redis

  • Se existir, obtenha o valor de KEY

String json=jedis.get(Key);
  • método joinPointm.getSignature () para obter a assinatura do método de destino

    • Queremos atribuir a assinatura do método da classe pai de joinPointm para usar a razão.
    • O resultado impresso mostra a assinatura do método alvo

Insira a descrição da imagem aqui

 MethodSignature methodSignature= (MethodSignature) joinPointm.getSignature();
  • Obtenha dinamicamente o tipo do método alvo com base na assinatura

  • getReturnType Obtenha o tipo da assinatura do método de destino atual (ou seja, o tipo do método de destino)

  • O resultado impresso mostra o tipo de método alvo

Insira a descrição da imagem aqui

 Class returnType = methodSignature.getReturnType();

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

result = RedisUtl.toObject(json, returnType);

2- O valor de KEY não existe no redis (consultar o banco de dados e armazená-lo no cache)

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();
    }
}
  • Se não houver dados de consulta no redis, execute diretamente o método de destino e coloque-o no banco de dados

  • joinPointm.proceed (); execute o método de destino

result =joinPointm.proceed(); 
  • O valor de retorno do método de destino que consulta o banco de dados é convertido para o tipo Json

String json=RedisUtl.toJSON(result);
  • No momento, não definimos o tempo limite. Se atingirmos o tempo limite no futuro, o tempo limite será maior que 0. Em seguida, defina o tempo limite que definimos ao armazenar

  • Armazene diretamente se não houver tempo limite

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

Expandir

Quando definimos anotações personalizadas, definimos o padrão sem tempo limite, portanto, se definirmos o tempo limite,
Insira a descrição da imagem aqui
adicionaremos o tempo limite quando a anotação personalizada descrever o método


3. Conclusão de negócios

retornar resultado - retorna o resultado da consulta do cliente
Insira a descrição da imagem aqui
A primeira consulta é o banco de dados, a
segunda consulta é o cache

Acho que você gosta

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