AOP细节1-10

13 篇文章 0 订阅

logUtil

package com.lyj.utils;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 如何将这个类(切面类)中的这些方法(通知方法)动态的在目标方法运行的各个位置切入
 * @author Administrator
 *
 */
@Order(1)//改变优先级,数值越小优先级越高
@Aspect
@Component
public class LogUtils {
	/**
	 * 告诉Spring每个方法都什么时候运行
	 *  [1]@Before:前置通知,在方法执行之前执行
		[2]@After:后置通知,在方法执行之后执行
		[3]@AfterRunning:返回通知,在方法返回结果之后执行
		[4]@AfterThrowing:异常通知,在方法抛出异常之后执行
		[5]@Around:环绕通知,围绕着方法执行
		
		抽取可重用的切入点表达式
		1.随便声明一个没有实现的返回void的空方法
		2.表注@Pointcut
	 */
	@Pointcut("execution(public int com.lyj.impl.MyCalc.*(int, int))")
	public void hahaPoint(){
		
	}
	
	
	//之前,写切入表达式
	//excution(方法权限 返回类型 方法签名)
	@Before("hahaPoint()")
	public static void logStart(JoinPoint joinPoint){
		//获取到目标方法运行时使用的参数
		Object[] args = joinPoint.getArgs();
		Signature signature = joinPoint.getSignature();
		String name = signature.getName();
		System.out.println("[LogUtils切面打印]【"+name+"】方法开始执行,用参数列表"+Arrays.asList(args));
	}
	/**
	 * 切入点表达式的写法:
	 * 固定格式:execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表]))
	 * 通配符:
	 * 		*:一个或多个字符
	 * 		      任意一个参数  ("execution(public int com.lyj.impl.MyCalc.*(int, *))"
	 * 		      匹配一层路径
	 * 		..:匹配任意多个参数,任意类型  execution(public int com.lyj.impl.MyCalc.*(..)
	 * 			匹配任意多层路径  execution(public int com.lyj..MyCalc*.*(..)
	 * 			权限位置不写就是任意权限
	 * 记住两种:
	 * 	最精确的:execution(public int com.lyj.impl.MaCalc.add(int,int))
	 * 	最模糊的:execution(* *.*(..))千万别写
	 * 
	 */
	//正常完成之后
	/**
	 * 告诉Springresult是干什么的
	 * @param joinPoint
	 * @param result
	 */
	@AfterReturning(value="hahaPoint()",returning="result")
	public static void logReturn(JoinPoint joinPoint,Object result){
		Signature signature = joinPoint.getSignature();
		String name = signature.getName();
		System.out.println("[LogUtils切面打印]【"+name+"】方法执行结束,计算结果是"+result);
	}
	/**
	 * 细节四:我们可以在通知方法运行的时候,拿到目标方法的详细信息
	 * 1)只需要为通知方法的参数列表上写一个参数
	 * 		JoinPoint joinPoint;封装了当前目标方法的详细信息
	 */
	//出现异常之后
	@AfterThrowing(value="hahaPoint()",throwing="exception")
	public static void logException(JoinPoint joinPoint,Exception exception){
		
		System.out.println("[LogUtils切面打印]【"+joinPoint.getSignature().getName()+"】方法执行出现异常,异常信息是"+exception);
	}
	//结束
	/**
	 * Spring对通知方法的要求不严格,唯一有要求的就是方法的参数列表一定不能乱写
	 * 通知方法是Spring利用反射调用的,每次方法调用的确定这个方法的参数表的值
	 * 参数表上的每一个参数,Spring都得知道是干嘛的,不知道的参数一定要告诉Spring
	 * @param joinPoint
	 */
	@After("hahaPoint()")
	public static void logEnd(JoinPoint joinPoint){
		System.out.println("[LogUtils切面打印]【"+joinPoint.getSignature().getName()+"】方法最终结束");
	}
	
	/**
	 * @throws Throwable 
	 * @Around:环绕通知  是Sping中最强大的同值
	 * 四合一通知就是环绕通知:环绕通知中有一个参数ProceedingJoinPoint pjp
	 * 环绕通知优先于普通通知执行
	 * 环绕方法还可以修改目标方法,普通方法不行
	 * 环绕只影响当前切面
	 */
	//@Around("hahaPoint()")
	public Object myAround(ProceedingJoinPoint pjp) throws Throwable{
		Object[] args = pjp.getArgs();
		String name = pjp.getSignature().getName();
		
		//利用反射推进目标方法运行,就是method.invoke(obj,args)
		Object proceed=null;
		try {
			System.out.println("环绕前置通知,"+name+"方法开始");
			proceed = pjp.proceed(args);
			System.out.println("环绕返回通知,"+name+"方法返回,返回值:"+proceed);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("环绕异常通知,"+name+"方法异常,异常信息:"+e);
		}finally{
			System.out.println("环绕后置通知,"+name+"方法结束");
		}
		//反射调用后的返回值也一定返回出去
		return proceed;
		
		
		
	}
	
}

ValidateAspect

package com.lyj.utils;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Order(2)
@Aspect
@Component
public class ValidateAspect {
	@Before("com.lyj.utils.LogUtils.hahaPoint()")
	public void logStart(JoinPoint joinPoint) {
		// 获取到目标方法运行时使用的参数
		Object[] args = joinPoint.getArgs();
		Signature signature = joinPoint.getSignature();
		String name = signature.getName();
		System.out.println("[validate切面]【" + name + "】方法开始执行,用参数列表" + Arrays.asList(args));
	}

	@AfterReturning(value = "com.lyj.utils.LogUtils.hahaPoint()", returning = "result")
	public static void logReturn(JoinPoint joinPoint, Object result) {
		Signature signature = joinPoint.getSignature();
		String name = signature.getName();
		System.out.println("[validate切面]【" + name + "】方法执行结束,计算结果是" + result);
	}

	@AfterThrowing(value = "com.lyj.utils.LogUtils.hahaPoint()", throwing = "exception")
	public static void logException(JoinPoint joinPoint, Exception exception) {

		System.out.println("[validate切面]【" + joinPoint.getSignature().getName()
				+ "】方法执行出现异常,异常信息是" + exception);
	}

	@After("com.lyj.utils.LogUtils.hahaPoint()")
	public static void logEnd(JoinPoint joinPoint) {
		System.out
				.println("[validate切面]【" + joinPoint.getSignature().getName() + "】方法最终结束");
	}
}

Test

/**
	 * 正常执行:@Before--@After--@AfterReturning
	 * 异常执行:@Before--@After--@AfterThrowing
	 */
	@Test
	public void test2(){
		MyCalc bean = ioc.getBean(MyCalc.class);
		//bean.div(1, 0);
		System.out.println("===========");
		bean.add(1, 1);
		
		
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值