首先

面向切面编程 AOP 即 Aspect Oriented Program

首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。

所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务
所谓的周边功能,比如性能统计,日志,事务管理等等

周边功能在Spring的面向切面编程AOP思想里,即被定义为切面
在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发

然后把切面功能和核心业务功能 "编织" 在一起,这就叫AOP

DEMO

一最近写的北京公交为例子吧,完成 操作日志 的功能

依赖

<!-- aop 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

定义日志注解

  • @Retention(RetentionPolicy.RUNTIME) 什么时候使用该注解,我们定义为运行时;
  • @Target({ ElementType.METHOD }) 注解用于什么地方,我们定义为作用于方法上;
  • 注解名为 OptLogAnnotation;
  • 定义一个属性 日志描述信息 ,默认为空字符串;
package cn.yiidii.panel.annotation;

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

/**
 * 日志注解
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OptLogAnnotation {

    String desc() default "";//日志描述信息

}

定义操作日志切面

aspectj 相关注解的作用

@Aspect:声明该类为一个注解类;
@Pointcut:定义一个切点,后面跟随一个表达式,表达式可以定义为切某个注解,也可以切某个 package 下的方法;
切点定义好后,就是围绕这个切点做文章了:

@Before: 在切点之前,织入相关代码;
@After: 在切点之后,织入相关代码;
@AfterReturning: 在切点返回内容后,织入相关代码,一般用于对返回值做些加工处理的场景;
@AfterThrowing: 用来处理当织入的代码抛出异常后的逻辑处理;
@Around: 环绕,可以在切入点前后织入代码,并且可以自由的控制何时执行切点;

package cn.yiidii.panel.advice;

import cn.yiidii.panel.annotation.OptLogAnnotation;
import cn.yiidii.panel.common.utils.IPUtil;
import cn.yiidii.panel.pojo.OptLog;
import cn.yiidii.panel.pojo.User;
import cn.yiidii.panel.service.impl.OptLogService;
import cn.yiidii.panel.shiro.util.SecurityUtil;
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.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Objects;

/**
 * 操作日志切面
 */
@Aspect
@Component
@Slf4j
public class OptLogAdvice {


    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OptLogService optLogService;

    @Around(value = "@annotation(cn.yiidii.panel.annotation.OptLogAnnotation)")//已注解 @OptLogAnnotation 为切点
    public void insertOptLog(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();//注解的方法
        OptLogAnnotation logAnnotation = method.getAnnotation(OptLogAnnotation.class);//注解
        OptLog optLog = packageOptLog(logAnnotation.desc(), "NO_MODULE");
        optLogService.insert(optLog);
    }

    private OptLog packageOptLog(String content, String module) {
        OptLog optLog = new OptLog();
        User user = SecurityUtil.getCurrUser();
        if (!Objects.isNull(user)) {
            optLog.setUid(user.getId());
            optLog.setSubject(user.getUsername());
        }
        String ip = IPUtil.getIpAddr(request);
        optLog.setIp(ip);
        optLog.setLocationInfo(IPUtil.getLocationByIP(ip));
        optLog.setModule(module);
        optLog.setContent(content);
        optLog.setCreateTime(new Date());
        return optLog;
    }

}

效果

optLog

  • 分类: JAVA
  • 标签: 无