spring boot 十八 redis (AOP 方式)

在上一章的基础上 。升级代码。

第一步加入 AOP

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>```

第二步 编写注解方法

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface MyRedis {

    String value() ;

    long expire() default -1;
    
}

第三步,编写AOP 处理方法

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class RedisHandle {

    @Autowired
    RedisTemplate redisTemplate;

    @Around("@annotation(myRedis)")
    public Object aroundMethod(ProceedingJoinPoint pjd, MyRedis myRedis) throws Throwable {

        Object[] args = pjd.getArgs();
        String key = myRedis.value();

        for (int i = 0; i < args.length; i++) {
            String replace = "#{" + i + "}";
            key = key.replace(replace, String.valueOf(args[i]));
        }

        ValueOperations valueOperations = redisTemplate.opsForValue();
        Object value = valueOperations.get(key);
        //redis 热点问题
        //服务器多线程并发访问时,可能会有多个线程同时访问为空,都会去执行设置操作,
        if (value == null) {
            //可能有多个线程阻塞在这里,当synchronized执行完成之后。
            synchronized (this){
                value = valueOperations.get(key);
                //每个线程进入后,发现如果已经有值了,就不再执行set操作
                if(value==null){
                    value = pjd.proceed();
                    valueOperations.set(key, value, myRedis.expire(), TimeUnit.SECONDS);
                }
            }
       }
        return value;
    }
}
    @MyRedis(value = "userkey#{0}", expire = 60 * 60 * 6)
    public User getUser(Long id) {
        ... 业务代码....
        return user;
    }
    
    @Override
    //这里的 value  是用于 redis 的可以 组拼方式
    //{1} 代表第二个参数来拼  {0} 就是第一个参数 举例如下:
    //  userKey#{1}   == userKey + name
    //  userKey#{0}   == userKey + id
    @MyRedis(value = "userKey#{1}", expire = 10)
    public User getUser(String id, String name) {
        System.out.println("读取数据库");
        return userDao.getUser(id);
    }

猜你喜欢

转载自blog.csdn.net/zhanglinlang/article/details/88432021