【java】通过spring通过AOP实现日志打印(二)

本人菜鸡一个,上一篇文章说了说自己对AOP的理解,并留下了一个用spring注解实现AOP的坑,本文就来填填这个坑

 

该系列暂时有两篇文章:

【java】java中的AOP思想(一):https://blog.csdn.net/lsr40/article/details/88642153

 

背景:

上一篇文章写了java中aop的思想,其实就是为了让某个方法运行的时候,(不用写多余的代码,就能)附带打印日志的功能,所以从另一种角度来说,这也是一种方法增强的效果,我们编写好了functionA方法,自动(增强)增加了该方法打印日志的功能。

当我们通过java编写web项目的时候,基本上都是用的spring的框架吧,所以本文来看看如何在spring通过注解的方式实现(AOP)方法增强

 

正文:

1、我们要在什么时候增强方法(寻找切点)?

2、我们要增强方法的什么(增强advice)?

3、确认编写代码(切点+增强的代码=切面!)

4、简单的模型:

假设我们现在需要编写一个所有的controller都中的方法都增强的切面我们需要做的是?

【java】通过spring通过AOP实现日志打印(二)_第1张图片

代码实现:

@Aspect
@Component
public class LogAspect {
	
    public LogAspect() {

    }
	
	//定义切点:所有拥有@RestController该注解的类里的方法都会被增强
	@Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
    public void logPointCut() {
    }

    /**
     * 使用Around来增强方法,记录系统日志
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行原有方法
        Object res = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
		//打印日志
		System.out.println("打印日志")
        return res;
    }

}

5、在模型上增加一些功能:

1、比如增加一个logService,然后把相关的日志保存到数据库,以便后续的分析!

2、那既然有了logService,就需要logMapper来实现数据库交互

3、我们总不能实时的往数据库插入日志吧,这样不管用户在你的网页中做什么操作都会插数据,很大程度上会影响数据库的性能,因此我们需要一个list来存放日志,并且定时插入数据

所以如图:

【java】通过spring通过AOP实现日志打印(二)_第2张图片

所以切面类基本代码和上面那段一样,只是新增了紫色的部分的代码,橙色框中的代码,我想作为一个java程序员,应该得会写的把,不就是Mybatis框架中往数据库中增加数据嘛,把list里的数据批量插入数据库,应该也没问题吧,因此这里就只剩下,中间的紫色的Service如何编写。

 

@Service
public class LogService {
    @Resource
    private LogMapper logMapper;
	//构造一个定时器
    private ScheduledExecutorService executorService;
	//创建一个线程安全的list,来存放日志对象
    private List controllerLogVOList = Collections.synchronizedList(new ArrayList());
	
	//定时器中开启一个线程来运行代码
    class LogRunnable implements Runnable {
        @Override
        public void run() {
            if (controllerLogVOList.size() != 0) {
                logMapper.saveConttollerLogList(controllerLogVOList);
				//保存完之后,清空list
                controllerLogVOList.clear();
            }
        }
    }
	//第一次调用保存日志的时候,构造定时器
    private void initScheduledExecutorService() {
        if (executorService == null) {
            executorService = Executors.newSingleThreadScheduledExecutor();
            executorService.scheduleAtFixedRate(
                    new LogRunnable(),
                    60000,
                    60000,
                    TimeUnit.MILLISECONDS);
        }
    }
	//提供给切面调用的保存数据的方法,将日志对象存到线程安全的list中,等待定时器调用logMapper批量存数据
    public void saveControllerLog(ControllerLogVO controllerLogVO) {
        initScheduledExecutorService();
        controllerLogVOList.add(controllerLogVO);
    }

}

那大概就是这样了~

 

然后我贴出一些我在写这篇文章时候,找到的一些好东西~

1、如上代码中用到了scheduleAtFixedRate,关于scheduleAtFixedRate与scheduleWithFixedDelay区别:https://lzhw1985.iteye.com/blog/1990829(作者:lzhw1985)

2、如果需要彻底全面的了解AOP,推荐这位大神的Spring中的AOP系列https://my.oschina.net/itblog?tab=newest&catalogId=431633(作者:摆渡者)

3、@Pointcut的用法:https://blog.csdn.net/qq_15037231/article/details/78159456(转载:斜阳雨陌)

4、Spring AOP 中@Pointcut的用法:https://www.cnblogs.com/liaojie970/p/7883687.html(作者:山高我为峰)

5、配置了 Spring AOP 但会调用两次的问题解决方法:https://blog.csdn.net/deniro_li/article/details/76139738(作者:deniro_li)

首先得谢谢提供本文代码的同事,还有就是昨天我领导说让我别天天四处玩,要多看源码,我觉得他说的有道理,很多框架不要光会用,还是要多研究研究为什么会有这样的框架出现,为什么框架的代码是这样,还是要多学习呀!~

本人菜鸡一只,如果有哪里写得不对,或者误导了大家的,请批评指出,本人一定虚心接受,坚决改正!

你可能感兴趣的:(java)