spring学习笔记十四 五种通知

一、五种通知

        1.前置通知

       2.后置通知

       3.返回通知

       4.异常通知

       5.环绕通知

spring学习笔记十四 五种通知_第1张图片

二.工程目录

       spring学习笔记十四 五种通知_第2张图片

三、工程文件

          定义一个接口  AtithmeticCalculator.java

          

package aop.impl;

import org.omg.PortableInterceptor.IORInterceptor;

public interface AtithmeticCalculator {
     int add(int i,int j);
     int sub(int i,int j);
     int mul(int i,int j);
     int div(int i,int j);
}

        实现这个接口AtithmeticCalculatorImpl.java

package aop.impl;

import org.springframework.stereotype.Component;

@Component("AtithmeticCalculator")
public class AtithmeticCalculatorImpl implements AtithmeticCalculator {

	@Override
	public int add(int i, int j) {
		int result=i+j;
		return result;
	}

	@Override
	public int sub(int i, int j) {
		int result=i-j;
		return result;
	}

	@Override
	public int mul(int i, int j) {
		int result=i*j;
		return result;
	}

	@Override
	public int div(int i, int j) {
		int result=i/j;
		return result;
	}

}

通知切面LoggingAspect.java

package aop.impl;

import java.util.Arrays;
import java.util.List;

import javax.management.RuntimeErrorException;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
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.springframework.stereotype.Component;

import com.mysql.fabric.xmlrpc.base.Array;

/*
 * 在aop.impl.AtithmeticCalculator接口的每一个实现类的每一个方法之前执行
 * 
 * */

@Aspect
@Component
public class LoggingAspect {

	@Before("execution(public int aop.impl.AtithmeticCalculator.*(..))")
	public void beforeMethod(JoinPoint joinPoint){
		String methodName=joinPoint.getSignature().getName();
		Object[] args=joinPoint.getArgs();
		System.out.println("The Method "+methodName+"begins"+Arrays.asList(args));
		
	}
	@After("execution(public int aop.impl.AtithmeticCalculator.*(..))")
	public void afterMethod(JoinPoint joinPoint){
		
		String methodName=joinPoint.getSignature().getName();
		System.out.println("The Method "+methodName+" end");
		
	}
	
	 /* 在方法正常结束后执行的代码
	 * 返回通知是可以访问到方法的返回值
	 */ 
	@AfterReturning(value="execution(public int aop.impl.AtithmeticCalculator.*(..))",
			returning="result")
	public void afterReturning(JoinPoint joinPoint,Object result){
		
		String methodName=joinPoint.getSignature().getName();
		System.out.println("The Method "+methodName+" end with"+result);
		
	}
	
	 /* 异常通知
	 * 在目标方法出现异常时会执行的代码
	 * 可以访问到异常对象,且可以指定在出现特定异常时再执行通知代码
	 */ 
	@AfterThrowing(value="execution(public int aop.impl.AtithmeticCalculator.*(..))",
			throwing="ex")
	public Object afterThrowing(JoinPoint joinPoint,Exception ex){
		String methodName=joinPoint.getSignature().getName();
		System.out.println("The Method "+methodName+" occurs excetion"+ex);
		return 100;
	}
	
	/* 环绕通知需要携带ProceedingJoinPoint类型的参数
	 * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法
	 * 且环绕通知必须有返回值,返回值即为目标方法的返回值
	 * 环绕通知是最强的,但是不是最常用的
	 * */
	/*@Around("execution(public int aop.impl.AtithmeticCalculator.*(..))")
	public Object aroundMethod(ProceedingJoinPoint pjd){
		
		Object result=null;
		String methodName=pjd.getSignature().getName();
		try {
			//前置通知
			System.out.println("The method"+methodName+" begins "+Arrays.asList(pjd.getArgs()));
			//执行目标方法
			result=pjd.proceed();
			//返回通知
			System.out.println("The "+methodName+"  ends result:"+result);
		} catch (Throwable e) {
			// 异常通知
			System.out.println("The "+methodName+" occurs exception:"+e);
			throw new RuntimeException(e);
		}
		//后置通知
		System.out.println("The method"+methodName+"ends");
		return result;
	}*/
}

配置文件AtithmeticCalculator.xml




    
    
    


测试类Main.java

package aop.impl;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {


	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//1.创建springIOC容器
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//2.从IOC容器中获取bean
		AtithmeticCalculator atithmeticCalculator=ctx.getBean(AtithmeticCalculator.class);
		//3.使用bean
		System.out.println(atithmeticCalculator.getClass().getName());
		int result=atithmeticCalculator.add(1, 5);
		System.out.println(result);
		
		result=atithmeticCalculator.sub(1, 5);
		System.out.println(result);
		
		result=atithmeticCalculator.mul(1, 5);
		System.out.println(result);
		//可以将除法里面的除数,改成0,测试异常通知
		result=atithmeticCalculator.div(1, 1);
		System.out.println(result);
	}

}

运行结果:

com.sun.proxy.$Proxy10
The Method addbegins[1, 5]
The Method add end
The Method add end with6
6
The Method subbegins[1, 5]
The Method sub end
The Method sub end with-4
-4
The Method mulbegins[1, 5]
The Method mul end
The Method mul end with5
5
The Method divbegins[1, 1]
The Method div end
The Method div end with1
1


在LoggingAspect.java可以将前置、后置、返回、异常通知使用环绕通知代替,替换代码:

@Around("execution(public int aop.impl.AtithmeticCalculator.*(..))")
	public Object aroundMethod(ProceedingJoinPoint pjd){
		
		Object result=null;
		String methodName=pjd.getSignature().getName();
		try {
			//前置通知
			System.out.println("The method"+methodName+" begins "+Arrays.asList(pjd.getArgs()));
			//执行目标方法
			result=pjd.proceed();
			//返回通知
			System.out.println("The "+methodName+"  ends result:"+result);
		} catch (Throwable e) {
			// 异常通知
			System.out.println("The "+methodName+" occurs exception:"+e);
			throw new RuntimeException(e);
		}
		//后置通知
		System.out.println("The method"+methodName+"ends");
		return result;
	}

四.总结

返回通知:在方法正常结束后执行的代码,返回通知是可以访问到方法的返回值

异常通知: 在目标方法出现异常时会执行的代替, 可以访问到异常对象,且可以指定在出现特定异常时再执行通知代码

环绕通知: 环绕通知需要携带ProceedingJoinPoint类型的参数,

                   环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法
           且环绕通知必须有返回值,返回值即为目标方法的返回值
           环绕通知是最强的,但是不是最常用的


你可能感兴趣的:(spring)