相同类中方法间调用时日志Aop失效处理
本篇分享的内容是在相同类中方法间调用时Aop失效处理方案,该问题我看有很多文章描述了,不过大多是从事务角度分享的,本篇打算从日志aop方面分享(当然都是aop,失效和处理方案都是一样),以下都是基于springboot演示;
- 快速定义个日志Appender
- 快速定义个拦截器和日志注解(aop)
- 模拟相同类中方法间调用时aop失效
- Aop失效处理方案(就两种足够了)
快速定义个日志Appender
日志我还是喜欢log4j,大部分朋友也同样吧,这里lombok与log4j结合来完成我们的日志,如下maven包(最新mvn还是建议去官网找):
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.-alpha0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>2.0.-alpha0</version>
</dependency>
先继承log4j的AppenderSkeleton重写下append方法,简单记录下就行,如下:
public class MyLogAppend extends AppenderSkeleton {
private String author;
public void setAuthor(String author) {
this.author = author;
}
@Override
protected void append(LoggingEvent loggingEvent) {
System.out.println(
JsonUtil.formatMsg("date -- {},level -- {},message -- {}",
LocalDate.now(),
loggingEvent.getLevel(),
loggingEvent.getMessage()));
}
@Override
public void activateOptions() {
super.activateOptions();
System.out.println("author:" + this.author);
}
@Override
public void close() {
this.closed = true;
}
@Override
public boolean requiresLayout() {
return false;
}
}
然后项目根目录增加log4j.properties配置文件,配置内容定义info级别,就此完成了log4j自定义记录日志了:
log4j.rootLogger=info,MyLogAppend
log4j.appender.MyLogAppend=com.sm.component.log.MyLogAppend
log4j.appender.MyLogAppend.author=shenniu003
快速定义个拦截器和日志注解(aop)
通常同类中不同方法调用是常事,可以直接用this.xx();有时有这样需求,需要各个调用方法时候的参数记录下来,因此我们需要个拦截器,再增加个自定义注解方便使用:
@Aspect
@Component
@Slf4j
public class MyLogInterceptor { private final String pointcut = "@annotation(com.sm.component.ServiceLog)"; @Pointcut(pointcut)
public void log() {
} @Before(value = "log()")
void before(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
log.info(
JsonUtil.formatMsg("method:{},params:{}",
signature.toLongString(),
joinPoint.getArgs()));
}
}
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceLog {
}
拦截器拦截带有@ServiceLog注解的方法,然后记录请求参数和方法名;
模拟相同类中方法间调用时aop失效
利用上面完成的日志注解,这里在OrderService类中用getOrderDetail方法去调用getOrderLog方法,他两都标记日志注解便于记录参数日志;同时getOrderDetail方法也调用另外一个UserService类中的getNickName方法,便于比较:
@Service
public class OrderService { @Autowired
UserService userService; @ServiceLog
public String getOrderDetail(String orderNum) {
String des = "订单号【" + orderNum + "】月饼一盒";
userService.getNickName(orderNum);
this.getOrderLog(orderNum + "");
return des;
} @ServiceLog
public List<String> getOrderLog(String orderNum) {
List<String> logs = new ArrayList<>();
IntStream.range(, ).forEach(b -> {
logs.add("用户" + b + "购买成功");
});
return logs;
}
}
@Service
public class UserService {
@ServiceLog
public String getNickName(String userId) {
return "神牛" + userId;
}
}
方法调用重点截图:

然后运行程序,接口触发调用getOrderDetail方法,以下拦截器中记录的日志信息:

能够看出拦截器只记录到了getOrderDetail和getNickName方法的日志,因此可以肯定getOrderLog根本没有走拦截器,尽管在方法上加了日志@ServiceLog注解也没用。
Aop失效处理方案(就两种足够了)
就上面相同类中方法间调用拦截器(aop)没起作用,我们有如下常用两种方式处理方案;
- 用@Autowired或Resource引入自身依赖
- 开启暴露代理类,AopContext.currentProxy()方式获取代理类
第一种:主要使用注解方法引入自身代理依赖,不要使用构造的方式会有循环依赖问题,以下使用方式:

第二种:通过暴露代理类方式,实际原理是把代理类添加到当前请求的ThreadLocal里面,然后在使用时从ThreadLocal中获取代理类,再调用对应的方法,开启方式需要:
@EnableAspectJAutoProxy(exposeProxy = true)
然后方法中如下使用即可:

最后来看下使用这两种方式正常走拦截器效果:

不管是日志拦截器或事务,他们都是aop的方式,底层原理走的代理方式,只有使用代理类才会正常执行拦截器,而this.xxx()使用的是自身实例对象,因此会出现上面失效的情况。
相同类中方法间调用时日志Aop失效处理的更多相关文章
- C#中方法的调用
C#中方法的调用 1.同一个类中方法的调用: 静态方法可以直接调用静态方法 静态方法不能直接调用非静态方法,静态方法先生成. 非静态方法可以直接调用静态方法 如果静态方法要调用非静态的方法,必须使用实 ...
- Spring service本类中方法互相调用事物失效问题
简介 Spring事物利用的是AOP,动态代理采用CGLIB代理(默认,也可以用Proxy代理,但是Proxy代理效率低于CGLIB代理).故只要弄懂Spring的AOP实现,就知道为什么servic ...
- JAVA中方法的调用主要有以下几种
JAVA中方法的调用主要有以下几种: 1.非静态方法 非静态方法就是没有 static 修饰的方法,对于非静态方法的调用,是通过对 象来调用的,表现形式如下. 对象名.方法() eg: public ...
- java中方法传入参数时:值传递还是址传递?
JAVA中的数据类型有两大类型: ① 基本数据类型:逻辑型(boolean).文本型(char).整数型(byte.short.int.long).浮点型(float.double) ② 引用数据类型 ...
- python__基础 : 多继承中方法的调用顺序 __mro__方法
在多继承中,如果一个子类继承了两个平级的父类,而这两个父类有两个相同名字的方法,那么一般先继承谁,调用方法就调用先继承的那个父类的方法.如: class A: def test(self): prin ...
- @Transactional-同一个类中方法自调,调用方法事物失效
问题分析 一个类中的方法调用另一个事物传播性为创建事物的方法,调用的方法事物失效? SpringAOP 代理的Service对象调用了其方法,这个方法再去调用这个Service中的其他方法是没有使用A ...
- 1.7Oob同类中不同方法间的互相调用
import java.util.Scanner; public class Bill { public static final double RATE=150.0; 这里没有创建getter和se ...
- android开发中关于继承activity类中方法的调用
android开发中关于继承activity类中的函数,不能在其他类中调用其方法. MainActivity.java package com.example.testmain; import and ...
- testNG中方法的调用顺序
今天在执行selnium的test case时,总是遇到空指针错误.但是以前也有run成功过,然后换了各种方法定位元素,都失败了,所以怀疑应该不是元素定位不到的问题,所以可能是method之间有依赖, ...
随机推荐
- Hyper-v设置linux固定ip
一.创建CentOS 7专用的虚拟交换机 打开Hyper-v控制面板,找到右边的“虚拟交换机管理器” 进去后,点击“新建虚拟网络交换机”,填写名称后,选择“内部” 打开网络中心,修改配置如下图,注意i ...
- jdk安装及环境配置
1.下载对应的安装包(我们公司用的是jdk 1.8) 2.选择对应版本,点击安装,在选择安装位置的时候,选择自己对应存放的位置,其他都点击下一步就行了,先安装jdk,后安装jre 3.环境变量,选择 ...
- 扩展欧几里德算法(递归及非递归实现c++版)
今天终于弄懂了扩展欧几里德算法,有了自己的理解,觉得很神奇,就想着写一篇博客. 在介绍扩展欧几里德算法之前,我们先来回顾一下欧几里德算法. 欧几里德算法(辗转相除法): 辗转相除法求最大公约数,高中就 ...
- JVM解剖乐园
1.JVM锁粗化和循环原文标题:JVM Anatomy Quark #1: Lock Coarsening and Loops 众所周知Hotsport编译器会进行JVM锁粗化和优化,它将相邻的锁区块 ...
- 解决!!-- krb5-libs.x86_64被卸载,yum不能使用,ssh不能连接
常在河边走哪有不湿鞋,常玩服务器哪有不搞挂几台,一不小心就搞挂了 今天删除 krb5-libs.x86_64下了狠功夫..... 用了命令: rpm -e --nodeps krb5-libs.x8 ...
- 常用高效 Java 工具类总结
一.前言 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选取的5万个开源项目源码 ...
- 纯css、js 的H5页面对接echarts
做项目时,会遇到一些零碎的技术点.记录下来以防忘记 需求:做可视化界面,但是需要兼容ie8,需要用纯css.js 的H5页面对接echarts,下面为效果图(带定时器循环显示tooltip). 实现方 ...
- Liunx学习总结(八)--服务
什么是服务 服务是向外提供服务的进程,一般来说都会放在后台,既然要持续不断的提供外界随时发来的服务请求,服务进程就需要常驻在内存中,且不应该和终端有关,否则终端退出服务程序就退出了.另外,要能够接待外 ...
- Vulkan(0)搭建环境-清空窗口
Vulkan(0)搭建环境-清空窗口 认识Vulkan Vulkan是新一代3D图形API,它继承了OpenGL的优点,弥补了OpenGL的缺憾.有点像科创板之于主板,歼20之于歼10,微信之于QQ, ...
- unity之游戏特效
一.运动轨迹 运动轨迹常常用于表现武器的挥舞效果,在提高速度感的同时又能让玩家看清楚招式动作,所以是常见的一种格斗特效. Unity中可以直接使用TrailRender来实现该效果. 二.运动模糊 运 ...