什么是AOP,如何书写的?

AOP全称Aspect Oriented Programming意为面向切面编程,也叫做面向方法编程,是通过预编译方式和运行期动态代理的方式实现不修改源代码的情况下给程序动态统一添加功能的技术。

 首先导入AOP依赖

        <!--AOP联盟-->
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <!--Spring Aspects-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--aspectj-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.3</version>
        </dependency>

创建自定义注解

package tech.niua.admin.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解, 用于帖子浏览量计数
 */
//注解用在方法上
@Target({ElementType.PARAMETER, ElementType.METHOD})
//@Retention的作用是定义被他所注解的注解保留多久,RUNTIME运行时
@Retention(RetentionPolicy.RUNTIME)
public @interface PostViewCount {

    String description()  default "";
}

切面类:

package tech.niua.admin.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import tech.niua.admin.util.RedisUtil;

/**
 * 帖子浏览量计数的切面
 */

//说明当前对象是一个切面
@Aspect
@Configuration
@Slf4j
public class PostViewAspect {

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 切入点
     */
    @Pointcut("@annotation(tech.niua.admin.annotation.PostViewCount)")
    public void PostViewAspect() {

    }

    /**
     * 切入处理
     * @param joinPoint
     * @return
     */

    //环绕通知,最强大的通知类型,可以控制方法入参、执行、返回结果登方面细节
    @Around("PostViewAspect()")
    public  Object around(ProceedingJoinPoint joinPoint) {
        Object[] object = joinPoint.getArgs();
        Object postId = object[0];
        log.info("postId:{}", postId);
        Object obj = null;
        try {
            String key = "postId_" + postId;
            // 浏览量存入redis中
            redisUtil.add(key);
            obj = joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return obj;
    }
}

创建Redis工具类,用来暂存浏览量

package tech.niua.admin.util;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * Redis 工具类, 用于暂存浏览量
 */

//允许在Spring IOC对当前对象实例化b并管理
@Component
public class RedisUtil {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    public void del(String... key) {
        redisTemplate.delete(key[0]);
    }

    /**
     * 计数
     *
     * @param key
     */
    public Long add(String key) {
        return redisTemplate.opsForValue().increment(key, 1);
    }

    /**
     * 获取浏览量
     *
     * @param key
     */
    public Integer size(String key) {
        return (Integer) redisTemplate.opsForValue().get(key);
    }

}

获取浏览量并存到数据库 

package tech.niua.admin.schedule;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tech.niua.admin.post.domain.Post;
import tech.niua.admin.post.service.IPostService;
import tech.niua.admin.util.RedisUtil;

import javax.annotation.Resource;
import java.util.List;


@Component
@Slf4j
@EnableScheduling
public class Schedule {
    @Resource
    private RedisUtil redisUtil;
    @Resource
    IPostService postService;

    /**
     * 定时保存帖子浏览量
     */

    //Scheduled定时器 每30秒触发一次
    @Scheduled(cron = "30 * * * * ? ")
    @Transactional(rollbackFor=Exception.class)
    public void savePostViewCount() {
        log.info("浏览量入库开始");
        QueryWrapper<Post> qw = new QueryWrapper<>();
        qw.select("id").eq("delete_flag", 0).eq("audit_status", 1);
        List<Object> list = postService.listObjs(qw);
        list.forEach(id -> {
            // 获取每一篇帖子在redis中的浏览量,存入到数据库中
            String key  = "postId_" + id;
            Integer readingVolume = redisUtil.size(key);
            if (readingVolume != null && readingVolume > 0) {
                Boolean updated = postService.setPostViewCount((Long) id, readingVolume);
                if (updated) {
                    log.info("{}:浏览量更新成功", id);
                    redisUtil.del(key);
                }
            }
        });
        log.info("浏览量入库结束");
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值