springboot 整合 aop

第一步:添加依赖 (这里我去除了spring-boot-starter-logging,因为项目中可能引入了其他日志,为了避免冲突,就直接去除了)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

第二步:定义切面类

@Aspect
@Component
@Log4j2
public class BizLogAspect /*implements ApplicationContextAware*/{//如果涉及到需要获取一些类的话,要继承plicationContextAware

/*private ApplicationContext applicationContext; bizLog是一个自定义注解
Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = ((MethodSignature) signature);
            EnableBizLog bizLog =methodSignature.getMethod().getAnnotation(EnableBizLog.class);
MyLogService bizLogObjectService = (MyLogService) applicationContext.getBean(bizLog.serviceclass());*/
​ 

//定义切点
@Pointcut("@annotation(com.myproject.test.annotation.EnableBizLog)")
public void apiPoinCut() {
}

​//前置通知 还可以添加参数
@Before("apiPoinCut() &&" + args(name,pass))
public void before(JoinPoint point,String name,String pass){
       log.info("用户名:" + name +",密码:" + pass);
       // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
}
// 环绕通知
 @Around("apiPoinCut()")
 public Object execute(ProceedingJoinPoint joinPoint) {
   log.info("方法执行前");
   joinPoint.proceed()
   log.info("方法执行后");
 }
// 后置通知
 @After(apiPoinCut())
 public void doAfterAdvice(JoinPoint joinPoint)
  {
   logger.info("后置最终通知执行了!!!!"); } 

  }
}


//自定义注解
/**
 * 记录编辑详细信息的标注
 * @author lw
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface EnableBizLog {
    /**
     * @return 查询数据库所调用的class文件
     */
    Class serviceclass();
    /**
     * @return 业务日志处理的class文件
     */
    Class bizLogService() default LogServiceImpl.class;
    /**
     * @return 前台字段名称
     */
    String feildName() default "id";
    /**
     * @return 具体业务操作名称
     */
    String handleName() default "";
    /**
     * @return 是否处理数字
     */
    Class dealNumFlag() default IService.class;
    /**
     * @return 前台字段名称 会员id
     */
    String commonField() default "id";

    /**
     * @return 操作对象
     */
    Class operateObject() default Member.class;

    /**
     * @return crm内部调用还是外部接口调用
     */
    String operateType() default "api";
}

 

附录

切入点表达式

  现在我们介绍一下最重要的切入点表达式:

  如上文所说,定义切入点时需要一个包含名字和任意参数的签名,还有一个切入点表达式,就是* findById*(..)这一部分。

  切入点表达式的格式:execution([可见性] 返回类型 [声明类型].方法名(参数) [异常])

  其中【】中的为可选,其他的还支持通配符的使用:

    *:匹配所有字符
      ..:一般用于匹配多个包,多个参数
      +:表示类及其子类

  运算符有:&&、||、!

切入点表达式关键词:   

    1)execution:用于匹配子表达式。

            //匹配com.cjm.model包及其子包中所有类中的所有方法,返回类型任意,方法参数任意
            @Pointcut("execution(* com.cjm.model..*.*(..))")
            public void before(){}

 

      2)within:用于匹配连接点所在的Java类或者包。

            //匹配Person类中的所有方法
            @Pointcut("within(com.cjm.model.Person)")
            public void before(){}

 

            //匹配com.cjm包及其子包中所有类中的所有方法

            @Pointcut("within(com.cjm..*)")
            public void before(){}

 

     3) this:用于向通知方法中传入代理对象的引用。
            @Before("before() && this(proxy)")
            public void beforeAdvide(JoinPoint point, Object proxy){
                  //处理逻辑
            }

 

      4)target:用于向通知方法中传入目标对象的引用。
            @Before("before() && target(target)
            public void beforeAdvide(JoinPoint point, Object proxy){
                  //处理逻辑
            }

 

      5)args:用于将参数传入到通知方法中。
            @Before("before() && args(age,username)")
            public void beforeAdvide(JoinPoint point, int age, String username){
                  //处理逻辑
            }
 
      6)@within :用于匹配在类一级使用了参数确定的注解的类,其所有方法都将被匹配。 

            @Pointcut("@within(com.cjm.annotation.AdviceAnnotation)") - 所有被@AdviceAnnotation标注的类都将匹配
            public void before(){}

  

      7)@target :和@within的功能类似,但必须要指定注解接口的保留策略为RUNTIME。
            @Pointcut("@target(com.cjm.annotation.AdviceAnnotation)")
            public void before(){}

 

      8)@args :传入连接点的对象对应的Java类必须被@args指定的Annotation注解标注。
            @Before("@args(com.cjm.annotation.AdviceAnnotation)")
            public void beforeAdvide(JoinPoint point){
                  //处理逻辑
            }

  

      9)@annotation :匹配连接点被它参数指定的Annotation注解的方法。也就是说,所有被指定注解标注的方法都将匹配。
            @Pointcut("@annotation(com.cjm.annotation.AdviceAnnotation)")
            public void before(){}

      10)bean:通过受管Bean的名字来限定连接点所在的Bean。该关键词是Spring2.5新增的。
            @Pointcut("bean(person)")
            public void before(){}

参考资料

https://blog.youkuaiyun.com/lmb55/article/details/82470388

https://www.cnblogs.com/lic309/p/4079194.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值