面向AOP切面编程

介绍: 面向切面就是把一些与业务无关的代码抽取出来封装起来, 在一些主业务代码需要使用代码的地方进行切入该代码

使用场景: 访问检查(访问控制层前进行登录的验证), 打印日志, 事物等

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();
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值