前言
你是不是還在類里面直接拿到日志對(duì)象調(diào)用方法來輸出日志燕侠?接下來教你如何簡(jiǎn)單使用AOP+自定義注解優(yōu)雅的實(shí)現(xiàn)一個(gè)日志記錄功能
提示:以下是本篇文章正文內(nèi)容镇草,案例僅供參考
一厉萝、技術(shù)介紹
1.AOP是什么恍飘?
在軟件業(yè),AOP為Aspect Oriented Programming的縮寫谴垫,意為:面向切面編程章母,通過預(yù)編譯方式和運(yùn)行期間動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)。AOP是OOP的延續(xù)翩剪,是軟件開發(fā)中的一個(gè)熱點(diǎn)乳怎,也是Spring框架中的一個(gè)重要內(nèi)容,是函數(shù)式編程的一種衍生范型前弯。利用AOP可以對(duì)業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離蚪缀,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性恕出,同時(shí)提高了開發(fā)的效率询枚。 --摘自百度百科
二、開始使用
1.代碼目錄結(jié)構(gòu)
2.開始編寫代碼
POM.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
咱們這里采用SpringBoot 寫一個(gè)按需注入的方式開啟注解浙巫,編寫一個(gè)按需注入的注解
package com.hyh.log.annotation;
import com.hyh.log.config.HyhLogAutoConfiguration;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
/**
* 開啟日志注解
*
* @Author: heyuhua
* @Date: 2021/1/28 15:32
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({HyhLogAutoConfiguration.class})
public @interface EnableHyhLog {
}
自動(dòng)配置類
package com.hyh.log.config;
import com.hyh.log.aspect.LogAspect;
import com.hyh.log.service.LogService;
import com.hyh.log.service.impl.LogServiceImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Log AutoConfiguration
*
* @Author: heyuhua
* @Date: 2021/1/28 16:02
*/
@ConditionalOnWebApplication
@Configuration(proxyBeanMethods = false)
public class HyhLogAutoConfiguration {
@Bean
public LogAspect logAspect() {
return new LogAspect();
}
@Bean
public LogService logService() {
return new LogServiceImpl();
}
}
自定義日志注解
package com.hyh.log.annotation;
import java.lang.annotation.*;
/**
* 日志注解
*
* @Author: heyuhua
* @Date: 2021/1/28 16:02
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HyhLog {
/**
* 描述
*
* @return
*/
String value() default "";
}
復(fù)制代碼
日志切面代碼編寫
package com.hyh.log.aspect;
import com.hyh.log.annotation.HyhLog;
import com.hyh.log.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import javax.annotation.Resource;
/**
* Log Aspect
*
* @Author: heyuhua
* @Date: 2021/1/28 16:02
*/
@Aspect
public class LogAspect {
/**
* 日志服務(wù)
*/
@Resource
private LogService logService;
/**
* 環(huán)繞操作
*
* @param point
* @param hyhLog
* @return
* @throws Throwable
*/
@Around("@annotation(hyhLog)")
public Object around(ProceedingJoinPoint point, HyhLog hyhLog) throws Throwable {
String className = point.getTarget().getClass().getName();
String methodName = point.getSignature().getName();
logService.info("【類】:{},【方法】:{}", className, methodName);
Object obj = point.proceed();
// do something
return obj;
}
/**
* 前置操作
*
* @param point
* @param hyhLog
* @return
* @throws Throwable
*/
@Before("@annotation(hyhLog)")
public void before(JoinPoint point, HyhLog hyhLog) throws Throwable {
logService.info("執(zhí)行前置操作..." + hyhLog.value());
// do something
}
/**
* 后置操作
*
* @param point
* @param hyhLog
* @return
* @throws Throwable
*/
@After("@annotation(hyhLog)")
public void after(JoinPoint point, HyhLog hyhLog) throws Throwable {
logService.info("執(zhí)行后置操作..." + hyhLog.value());
// do something
}
}
復(fù)制代碼
日志服務(wù)接口
package com.hyh.log.service;
/**
* Log 接口
*
* @Author: heyuhua
* @Date: 2021/1/28 15:37
*/
public interface LogService {
/**
* info
*
* @param msg
*/
void info(String msg);
/**
* info
*
* @param msg
* @param o
*/
void info(String msg, Object o);
/**
* info
*
* @param msg
* @param throwable
*/
void info(String msg, Throwable throwable);
/**
* info
*
* @param msg
* @param o
*/
void info(String msg, Object... o);
/**
* info
*
* @param msg
* @param o
* @param throwable
*/
void info(String msg, Object o, Throwable throwable);
/**
* error
*
* @param msg
*/
void error(String msg);
/**
* error
*
* @param msg
* @param o
*/
void error(String msg, Object o);
/**
* error
*
* @param msg
* @param throwable
*/
void error(String msg, Throwable throwable);
/**
* error
*
* @param msg
* @param o
* @param throwable
*/
void error(String msg, Object o, Throwable throwable);
}
復(fù)制代碼
日志服務(wù)接口實(shí)現(xiàn)
package com.hyh.log.service.impl;
import com.hyh.log.service.LogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
/**
* 日志服務(wù)接口實(shí)現(xiàn)
*
* @Author: heyuhua
* @Date: 2021/1/28 17:04
*/
@Service
public class LogServiceImpl implements LogService {
/**
* 日志
*/
private static final Logger LOGGER = LoggerFactory.getLogger(LogServiceImpl.class);
@Override
public void info(String msg) {
LOGGER.info(msg);
}
@Override
public void info(String msg, Object o) {
LOGGER.info(msg, o);
}
@Override
public void info(String msg, Throwable throwable) {
LOGGER.info(msg, throwable);
}
@Override
public void info(String msg, Object... o) {
LOGGER.info(msg, o);
}
@Override
public void info(String msg, Object o, Throwable throwable) {
LOGGER.info(msg, o, throwable);
}
@Override
public void error(String msg) {
LOGGER.error(msg);
}
@Override
public void error(String msg, Object o) {
LOGGER.error(msg, o);
}
@Override
public void error(String msg, Throwable throwable) {
LOGGER.error(msg, throwable);
}
@Override
public void error(String msg, Object o, Throwable throwable) {
LOGGER.error(msg, o, throwable);
}
}
復(fù)制代碼
三金蜀、單元測(cè)試
OK,不廢話的畴,直接上單元測(cè)試渊抄,先在SpringBoot項(xiàng)目中開啟使用我們的注解
看紅框框選的我們寫的一個(gè)按需導(dǎo)入的注解丧裁,然后Controller層寫一個(gè)接口护桦,使用HyhLog注解
@HyhLog(value = "hello world test")
@RequestMapping(value = "hello", method = RequestMethod.GET)
public String hello() {
return "hello";
}
訪問hello接口來看下執(zhí)行結(jié)果
總結(jié)
AOP基于動(dòng)態(tài)代理可以實(shí)現(xiàn)很多功能,例如權(quán)限控制渣慕、日志記錄嘶炭、事務(wù)提交與回滾等一系列操作,通過無(wú)侵入式的方式實(shí)現(xiàn)業(yè)務(wù)解耦逊桦、功能強(qiáng)化,讓我們能用最優(yōu)雅的代碼實(shí)現(xiàn)最復(fù)雜的功能眨猎。