Spring AOP(一)——基于注解的方式

3 篇文章 0 订阅
本文介绍了如何在Spring框架中使用AOP进行增强,重点在于基于注解的配置方式。首先,列举了需要导入的jar包,然后详细说明了在配置文件中添加aop命名空间的步骤。接着,讨论了四种不同类型的注解通知:前置通知(@Before),后置通知(@After),返回通知,异常通知,并提到可以使用@Order注解来定义切面的执行顺序。
摘要由CSDN通过智能技术生成

步骤

1.导入jar包:


com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.2.4.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar

spring-beans-4.2.4.RELEASE.jar
spring-context-4.2.4.RELEASE.jar
spring-core-4.2.4.RELEASE.jar
spring-expression-4.2.4.RELEASE.jar
com.springsource.org.apache.commons.logging-1.1.1.jar


2.在配置文件中加入aop 的命名空间

xmlns:aop=“http://www.springframework.org/schema/aop”

3.基于注解的方式

a.在配置文件中加入如下配置:
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.atguigu.spring.aop.impl"></context:component-scan>
<!-- 使用AsoectJ 注解起作用:自动匹配的类生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
b.把横切关注点的代码抽象到切面的类中
	i.首先是需要把该类放入到IOC容器中,即加入@Component 注解
	ii.切面还需要加入@Aspect 注解
@Aspect
@Component
public class LoggingAspect {
}
c.在类中声明各种通知
	i.声明一个方法
	ii.在方法前加入一个@Before/@After/@Around/@AfterReturning/@AfterThrowing 注解
  • 前置通知@Before
@Aspect
@Component
public class LoggingAspect {
	
	//声明该方法是一个前置通知,在目标方法之前执行
	@Before("execution(* com.atguigu.spring.aop.impl.*.*(..))")
	public void beforeMethod() {
		System.out.println("The method begins");
	}
}
d.可以在通知方法中声明一个类型为 JoinPoint 的参数,然后就能访问链接细节,入方法名称和参数值
@Aspect
@Component
public class LoggingAspect {
	
	//声明该方法是一个前置通知,在目标方法之前执行
	@Before("execution(* com.atguigu.spring.aop.impl.*.*(..))")
	public void beforeMethod(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		List<Object> args = Arrays.asList(joinPoint.getArgs());
		System.out.println("The method "+ methodName +" begins with" + args);
	}
}
  • 后置通知@After
    /**
     *目标方法执行后(无论是否发生异常),执行的通知
	 *在后置通知中还不能访问目标方法执行的结果
	 */
	@After("execution(* com.atguigu.spring.aop.impl.*.*(..))")
	public void afterMethod(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		System.out.println("The method "+ methodName +" end ");
	}
  • 返回通知
	//在方法正常结束后执行的代码,可以访问到方法的返回值
	@AfterReturning(value = "execution(* com.atguigu.spring.aop.impl.*.*(..))" , returning = "result")
	public void afterReturning(JoinPoint joinPoint,Object result) {
		String methodName = joinPoint.getSignature().getName();
		System.out.println("The method " + methodName+ " end result:" + result);
	}
  • 异常通知
	//在方法出现异常时会执行的代码,可以访问到异常对象,且可以指定再出现特定异常时在执行通知代码
	@AfterThrowing(value = "execution(* com.atguigu.spring.aop.impl.*.*(..))",throwing = "ex")
	public void afterThrowing(JoinPoint joinPoint,Exception ex) {
		String methodName = joinPoint.getSignature().getName();
		System.out.println("The method " + methodName +" occurs exception:" + ex );
	}
  • 环绕通知
	/**
	 * 环绕通知需要携带ProceedingJoinPoint 类型参数,
	 *环绕通知类似于动态代理的全过程:ProceedingJoinPoint 类型的参数可以决定是否执行目标方法
	 *且环绕通知必须有返回值,返回值即为目标方法的返回值
	 */
	@Around("execution(* com.atguigu.spring.aop.impl.*.*(..)))")
	public Object aroundMethod(ProceedingJoinPoint pjd) {
		
		Object result = null;
		String methodName = pjd.getSignature().getName();
		//执行方法
		try {
			//前置通知
			System.out.println("The method " + methodName+ " begins with" + Arrays.asList(pjd.getArgs()));
			result = pjd.proceed();
			//返回通知
			System.out.println("The method " + methodName + " end with:" + result);
		} catch (Throwable e) {
			System.out.println("The method " + methodName + " occurs exception:" + e);
			
		}
		System.out.println("The method " + methodName + " ends ");
		return 100;
		
	}

这里我们可以看到每次申明通知时都要写:

execution(* com.atguigu.spring.aop.impl.*.*(..))

所以我们可以把它提取出来

 - 定义一个方法,用于声明切入点表达式,该方法中在不需要填入其他的代码
 - 使用@Pointcut 来声明切入点表达式,后面的其他通知直接使用方法名来引用当前的切入点表达式
	@Pointcut("execution(* com.atguigu.spring.aop.impl.*.*(..)))")
	public void declareJoinPointExpression() {}
	
	@Before("declareJoinPointExpression()")
	public void beforeMethod(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		List<Object> args = Arrays.asList(joinPoint.getArgs());
		System.out.println("The method "+ methodName +" begins with" + args);
	}
- 如果是外面的类引用该表达式则使用  类名.方法名
@Aspect
@Component
public class VlidationAspect {
	@Before("LoggingAspect.declareJoinPointExpression()")
	public void validataArgs(JoinPoint joinPoint) {
		System.out.println("--->validate:" +Arrays.asList(joinPoint.getArgs()));
	}
}

另外:如果有多个切面,我们可以使用@Order 指明切面的优先级

@Order(1)
@Aspect
@Component
public class VlidationAspect {
}
@Order(2)
@Aspect
@Component
public class LoggingAspect {
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值