1.什么是AOP切面编程
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理,如下图所示:
相关引用 JavaGuide
2.多个切面的执行顺序如何控制?
// 值越小优先级越高
@Order(3)
@Component
@Aspect
public class LoggingAspect implements Ordered {
@Component
@Aspect
public class LoggingAspect implements Ordered {
// ....
@Override
public int getOrder() {
// 返回值越小优先级越高
return 1;
}
}
3. 使用切面编程实现日志打印
自定义注解
/**
* 调用方法时打印日志
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InvokeLog {
}
课程学习截图
配置类
import com.chehejia.osd.server.common.auth.ContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* InvokeLog 切面类
*
*/
@Aspect
@Component
@Slf4j
public class InvokeLogAspect {
/**
* 获取切入点
*/
@Pointcut("@annotation(com.chehejia.osd.server.common.annotation.log.InvokeLog)")
public void logPointCut() {
}
/**
* 方法执行前的动作
*
* @param point 连接点的信息
*/
@Before("logPointCut()")
private void logBefore(JoinPoint point) {
try {
String className = point.getTarget().getClass().getSimpleName();
String methodName = point.getSignature().getName();
log.info("=======>[{}::{}]accept request: {}, {}", className, methodName, ContextHolder.getOwnerId(), point.getArgs());
}
catch (Exception e) {
log.error("前置log切面设置失败。method:{}, message:{}, trace:{}", point.getSignature().getClass().getName(), e.getMessage(), e.getCause());
}
}
/**
* 方法执行完毕,返回前的动作
*
* @param point 连接点信息
* @param result 方法返回值
*/
@AfterReturning(value = "logPointCut()", returning = "result")
private void logAfter(JoinPoint point, Object result) {
try {
String className = point.getTarget().getClass().getSimpleName();
String methodName = point.getSignature().getName();
log.info("=======>[{}::{}]success result: {}, {}", className, methodName, ContextHolder.getOwnerId(), result);
}
catch (Exception e) {
log.error("后置log切面设置失败。method:{}, message:{}, trace:{}", point.getSignature().getClass().getName(), e.getMessage(), e.getCause());
}
}
}
4.Demo
import com.chehejia.osd.server.common.auth.ContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class InvokeLogAspect {
/**
* 获取切入点
*/
@Pointcut("@annotation(com.chehejia.osd.server.common.annotation.log.InvokeLog)")
public void logPointCut() {
}
/**
* 方法执行前的动作
*
* @param point 连接点的信息
*/
@Before("logPointCut()")
private void logBefore(JoinPoint point) {
try {
String className = point.getTarget().getClass().getSimpleName();
String methodName = point.getSignature().getName();
log.info("=======>[{}::{}]accept request: {}, {}", className, methodName, ContextHolder.getOwnerId(), point.getArgs());
}
catch (Exception e) {
log.error("前置log切面设置失败。method:{}, message:{}, trace:{}", point.getSignature().getClass().getName(), e.getMessage(), e.getCause());
}
}
/**
* 方法执行完毕,返回前的动作
*
* @param point 连接点信息
* @param result 方法返回值
*/
@AfterReturning(value = "logPointCut()", returning = "result")
private void logAfter(JoinPoint point, Object result) {
try {
String className = point.getTarget().getClass().getSimpleName();
String methodName = point.getSignature().getName();
log.info("=======>[{}::{}]success result: {}, {}", className, methodName, ContextHolder.getOwnerId(), result);
}
catch (Exception e) {
log.error("后置log切面设置失败。method:{}, message:{}, trace:{}", point.getSignature().getClass().getName(), e.getMessage(), e.getCause());
}
}
}
import java.lang.annotation.*;
/**
* 调用方法时打印日志
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InvokeLog {
}
5. 极海讲切面
极海讲切面
// TODO