介绍: 面向切面就是把一些与业务无关的代码抽取出来封装起来, 在一些主业务代码需要使用代码的地方进行切入该代码
使用场景: 访问检查(访问控制层前进行登录的验证), 打印日志, 事物等
AOP的相关术语
连接点(JoinPoint) : 连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点(被代理对象的所有方法)
切点(Pointcut): 切入点是指我们要对哪些Joinpoint进行拦截的定义(被代理对象加强的方法)
通知(Advice) : 通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
目标对象(target): 代理的目标对象, 被通知的对象,也就是真正的业务逻辑;
织入(weaving) : 是指把增强应用到目标对象来创建新的代理对象的过程(生成代理对象的过程)
切面(Aspect) : 是切入点和通知的结合,以后咱们自己来编写和配置的
AOP的通知类型
前置通知 : 在目标类的方法执行之前执行。
配置文件信息:<aop: before method=“before” pointcut-ref=“myPointcut3”/>
注解方式,贴在方法上: @Before("controllerAop()")
应用:可以对方法的参数来做校验
最终通知 : 在目标类的方法执行之后执行,如果程序出现了异常,最终通知也会执行。
在配置文件中编写具体的配置:<aop:after method=“after” pointcut-ref=“myPointcut3”/>
注解方式,贴在方法上: @After("controllerAop()")
应用:例如像释放资源
后置通知 : 方法正常执行后的通知。
在配置文件中编写具体的配置:<aop:after-returning method=“afterReturning” pointcut-ref=“myPointcut2”/>
应用:可以修改方法的返回值
异常抛出通知 : 在抛出异常后通知
在配置文件中编写具体的配置:<aop:after-throwing method=“afterThorwing” pointcut-ref=“myPointcut3”/>
应用:包装异常的信息
环绕通知: 方法的执行前后执行。环绕通知使用灵活.其他方式都能用环绕方式实现。
在配置文件中编写具体的配置:<aop:around method=“around” pointcut-ref=“myPointcut2”/>
要注意:目标的方法默认不执行,需要使用ProceedingJoinPoint对来让目标对象的方法执行。
原文链接:https://blog.csdn.net/ityqing/article/details/105271793
package com.fish.config;
import com.alibaba.fastjson.JSON;
import com.fish.aop.AopChannel;
import com.fish.aop.channel.CheckAdminOlineChannel;
import com.fish.aop.channel.CheckClientOlineChannel;
import com.fish.aop.channel.CheckClientSignChannel;
import com.fish.common.servlet.ServletUtils;
import com.fish.dao.redis.RedissonDao;
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.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamSource;
import org.springframework.stereotype.Component;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
/**
* aop切面
*/
@Aspect
@Component
@Slf4j
public class ControllerAopConfig {
@Value("${controller.log.show.enable}")
private boolean isShowControllerLog;
@Autowired
private RedissonDao redisson;
private List<AopChannel> aopchannels = new ArrayList<AopChannel>(9) {
private static final long serialVersionUID = -689595264093084192L;
{
//需要执行的切面逻辑
add(new CheckAdminOlineChannel());
add(new CheckClientOlineChannel());
add(new CheckClientSignChannel());
}
};
/**
* 指定切入的路径
*/
@Pointcut("execution(public * com.fish.controller..*.*(..))")
public void controllerAop() {
}
/**
* 执行方法之前切入
* @param joinPoint
* @throws Exception
*/
@Before("controllerAop()")//指定哪个路径进行切面
public void doBefore(JoinPoint joinPoint) throws Exception {
printLog(joinPoint);
for (AopChannel aopChannel : aopchannels) {
aopChannel.exec(joinPoint);
}
}
/**
* 执行方法之后返回的内容
* @param ret
* @throws Throwable
*/
@AfterReturning(returning = "ret",pointcut = "controllerAop()")
public void doAfterReturning(Object ret) throws Throwable {
redisson.unlock();
}
/**
* 打印日志
* @param joinPoint
*/
private void printLog(JoinPoint joinPoint) {
if (!isShowControllerLog){
return;
}
try {
HttpServletRequest request = ServletUtils.getRequest();
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getName();
System.out.println("=====================new Request======================");
System.out.println("-----logger aop"+log);
log.info("Request URL:"+request.getRequestURL());
Object[] args = joinPoint.getArgs();
System.out.println("params: ");
if (args!=null){
for (Object arg : args) {
if (
arg instanceof ServletResponse ||
arg instanceof ServletRequest ||
arg instanceof InputStreamSource
){
//不打印
continue;
}else {
System.out.println(" "+ JSON.toJSONString(arg));
}
}
}
System.out.println("UserKey:"+ request.getHeader("UserKey"));
System.out.println("Class Method:"+className+"."+methodName+"()"+"From IP:"+request.getRemoteAddr());
System.out.println("======================================================");
}catch (Exception e){
// e.printStackTrace();
}
}
}