Spring_06 AOP-前置通知、返回通知、异常通知、环绕通知(@AspectJ注解实现)

准备工作

  1. 需要jdk5.0及以上。
  2. 引入所需jar包,在03节导入的jar包,使用注解操作aop时会出错,故新上传一份jar包文件,可在文章末尾进行下载。
  3. 需要在配置文件中勾选aop、context命名空间(若果没有在本地配置,则需要联网)。

关于@AspectJ

  • 这是一个面向切面的框架,可以是aop使用更加便捷、灵活。
  • 与xml文件方式不同的是需要添加一个切入点函数(返回值为void,函数体为空)。

@Aspect包含的注解

  • @Aspect:用于定义一个切面。
  • @Pointcut:用于定义一个切入点。
  • @Before:用于定义一个前置通知。通常需要一个value属性,用于指定一个切入点表达式。
  • @AfterReturning:用于定义一个后置通知。 有pointcut、value、returning三个属性,pointcut和value属性都用于指定切入点表达式,returning属性可用于访问目标方法的返回值,属性值与通知方法中的形参名一致。
  • @AfterThrowing:用于定义一个异常通知。有pointcut、value、throwing三个属性,pointcut和value属性都用于指定切入点表达式,throwing属性用于访问目标方法抛出的异常,该属性值与异常通知方法中的参数一致。
  • @Around:用于一个环绕通知。有一个value属性,用于指定该通知被植入的切入点。
  • @After:用于定义最终final通知,不管是否异常,该通知都会执行。使用时需要指定一个value属性,用于指定该通知被植入的切入点

核心代码

package com.sunqg.service.imp;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.sunqg.service.ProductService;

@Component("productService")
public class ProductServiceImp implements ProductService {


	@Override
	public void browseBefore(String loginName, String ProductName) {
		// TODO Auto-generated method stub
		System.out.print("执行业务方法  前置通知");
	}

	@Override
	public void browseThrow(String loginName, String productName) {
		// TODO Auto-generated method stub
		System.out.print("模拟用户浏览 异常通知");
		throw new RuntimeException("特定的异常通知");
	}

	@Override
	public void browseAround(String loginName, String productName) {
		// TODO Auto-generated method stub
		System.out.print("模拟用户浏览  环绕通知");
		
		//延长方法的执行时间编便于展示环绕通知的效果
		int i = 100000;
		while(i>0)
			i--;
		
	}

	@Override
	public void browseAfter(String loginName, String productName) {
		// TODO Auto-generated method stub
		System.out.print("模拟用户浏览  返回通知");
		
	}

}

package com.sunqg.aop;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

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

/*
 * 定义切面类在此类中编写通知
 * 
 */

@Aspect
@Component("allLogAdvice")
public class AllLogAdvice {

	//定义切入点表达式,使用一个返回值为void、方法体为空的方法来命名切入点
	@Pointcut("execution(* com.sunqg.service.imp.ProductServiceImp.*(..))")
	private void allMethod(){}
	
	//使用此方法作为前置通知-日志
	@Before("allMethod()")
	public void BeforeAdvice(JoinPoint joinPoint){
		//获取业务方法的参数  通过getArgs方法可获得业务方法的参数
		List<Object> args = Arrays.asList(joinPoint.getArgs());
		
		//定义日志格式
		String logInfoText = "\n前置通知:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
				+args.get(1).toString() + "浏览商品" + args.get(1).toString();
		
		//输出日志
		System.out.print(logInfoText);
	}
	
	@AfterReturning("allMethod()")
	public void AfterAdvice(JoinPoint joinPoint){
		//获取方法参数
		List <Object> args = Arrays.asList(joinPoint.getArgs());
		String logInfoText = "\n返回通知:" + new SimpleDateFormat("yyy-MM-dd HH:mm:ss").format(new Date())
				+ args.get(1).toString();
		System.out.print(logInfoText);
	}
	
	@AfterThrowing(pointcut="allMethod()", throwing="e")
	public void ThrowAdvice(JoinPoint joinPoint,Exception e){
		//获取被调用的类名
		String targetClassName = joinPoint.getTarget().getClass().getName();
		
		//获取被调用的方法名
		String targetMethodName = joinPoint.getSignature().getName();
		
		//定义日志格式的字符串
		String logInfoText = "\n异常通知:执行" + targetClassName + "类的" + targetMethodName + "方法时出现异常";
		
		//将日志信息输出
		System.out.println(logInfoText);
	}
	@Around("allMethod()")
	public void AroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable{
		long beginTime = System.currentTimeMillis();
		joinPoint.proceed();
		long endTime = System.currentTimeMillis();
		
		//获取被调用的方法名
		String targetMethodName = joinPoint.getSignature().getName();
		
		//日志格式字符串
		String  logInfoText = "\n环绕通知:" + targetMethodName + "方法调用前的时间为" + beginTime + "毫秒," + "调用后的时间为:"
		+ endTime + "毫秒";
		
		System.out.print(logInfoText);
	}
}

package com.sunqg.test;

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

import com.sunqg.service.ProductService;
import com.sunqg.service.UserService;


public class TestLogin {
	@Test
	public void main(){
		//1.加载applicationContext文件
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		ProductService productService = (ProductService) ctx.getBean("productService");
		
		productService.browse("sunqg", "框架技术精讲与案例整合");

	}
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

	<!-- 配置自动扫描的包 -->
	<context:component-scan base-package="com.sunqg"></context:component-scan>
	<!-- 开启基于@AspectJ切面的注解处理器 -->
	<aop:aspectj-autoproxy/>
	
</beans>

aop注解所需的jar包

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值