一、xml配置方式
<!-- 目标对象
arithmeticCalculatorImpl类,是实现 add sub mul dvi (加减乘除)四个方法的类。这个类就是目标对象,即在计算的前后加上日志。
-->
<bean id="arithmeticCalculatorImpl" class="com.atguigu.spring.aspectJ.xml.ArithmeticCalculatorImpl"></bean>
<!--切面类
LoggingAspect记录日志的类,有5个方法
beforeMethod: 被注入方法(比如add方法)执行前执行的方法;
afterMethod: 被注入方法(比如add方法)执行后执行的方法;
afterReturningMethod: 被注入方法(比如add方法)执行返回时执行的,
如果add方法异常,则此方法不执行;
afterThrowingMethod: 被注入方法(比如add方法)出现异常后执行的方法;
aroundMethod: 可以实现上述四种方法。
-->
<bean id="loggingAspect" class="com.atguigu.spring.aspectJ.xml.LoggingAspect">
</bean>
<bean id="validationAspect" class="com.atguigu.spring.aspectJ.xml.ValidationAspect">
</bean>
<!-- AOP: 切面 通知 切入点表达式 -->
<aop:config>
<!-- 切面 -->
<aop:aspect ref="loggingAspect" order="2">
<!-- 切入点表达式 -->
<aop:pointcut expression="execution(* com.atguigu.spring.aspectJ.xml.*.*(..))" id="myPointCut"/>
<!-- 通知 -->
<aop:before method="beforeMethod" pointcut-ref="myPointCut"/>
<aop:after method="afterMethod" pointcut-ref="myPointCut"/>
<aop:after-returning method="afterReturningMethod" pointcut-ref="myPointCut" returning="result"/>
<aop:after-throwing method="afterThrowingMethod" pointcut-ref="myPointCut" throwing="ex"/>
<!-- <aop:around method="aroundMethod" pointcut-ref="myPointCut"/> -->
</aop:aspect>
<aop:aspect ref="validationAspect" order="1">
<aop:before method="beforeMethod" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
</beans>
/**
* 日志切面
*/
public class LoggingAspect {
public void beforeMethod(JoinPoint joinPoint) {
//获取方法的参数
Object [] args = joinPoint.getArgs();
//方法的名字
String methodName = joinPoint.getSignature().getName();
System.out.println("LoggingAspect==> The method "+methodName+" begin with "+ Arrays.asList(args));
}
public void afterMethod(JoinPoint joinPoint) {
//方法的名字
String methodName = joinPoint.getSignature().getName();
System.out.println("LoggingAspect==> The method " + methodName +" ends .");
}
public void afterReturningMethod(JoinPoint joinPoint,Object result ) {
//方法的名字
String methodName = joinPoint.getSignature().getName();
System.out.println("LoggingAspect==> The method " + methodName + " end with :" + result );
}
public void afterThrowingMethod(JoinPoint joinPoint,ArithmeticException ex ) {
//方法的名字
String methodName = joinPoint.getSignature().getName();
System.out.println("LoggingAspect==> Thew method " + methodName + " occurs Exception: " +ex );
}
public Object aroundMethod(ProceedingJoinPoint pjp) {
//执行目标方法
try {
//前置
Object result = pjp.proceed();
//返回
return result ;
} catch (Throwable e) {
//异常通知
e.printStackTrace();
}finally {
// 后置
}
return null;
}
}
二、注解方式
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.atguigu.spring.aspectJ.annotation"></context:component-scan>
<!-- 基于注解使用AspectJ: 主要的作用是为切面中通知能作用到的目标类生成代理. -->
<aop:aspectj-autoproxy/>
</beans>
package com.atguigu.spring.aspectJ.annotation;
import java.util.Arrays;
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.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 日志切面
*/
@Component //标识为一个组件
@Aspect //标识为一个切面
@Order(2) // 切面类执行的优先级,即执行顺序,order后数字越小,优先级越高
public class LoggingAspect {
/**
* 声明切入点表达式
*/
@Pointcut("execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))")
public void declarePointCut() {}
/**
* 前置通知: 在目标方法(连接点)执行之前执行.
*/
@Before("execution(public int com.atguigu.spring.aspectJ.annotation.ArithmeticCalculatorImpl.add(int,int))")
public void beforeMethod(JoinPoint joinPoint) {
//获取方法的参数
Object [] args = joinPoint.getArgs();
//方法的名字
String methodName = joinPoint.getSignature().getName();
System.out.println("LoggingAspect==> The method "+methodName+" begin with "+ Arrays.asList(args));
}
/**
* 后置通知: 在目标方法执行之后执行, 不管目标方法有没有抛出异常. 不能获取方法的结果
* * com.atguigu.spring.aspectJ.annotation.*.*(..)
* * : 任意修饰符 任意返回值
* * : 任意类
* * : 任意方法
* ..: 任意参数列表
*
* 连接点对象: JoinPoint
*/
//@After("execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))")
@After("declarePointCut()")
public void afterMethod(JoinPoint joinPoint) {
//方法的名字
String methodName = joinPoint.getSignature().getName();
System.out.println("LoggingAspect==> The method " + methodName +" ends .");
}
/**
* 返回通知: 在目标方法正常执行结束后执行. 可以获取到方法的返回值.
*
* 获取方法的返回值: 通过returning 来指定一个名字, 必须要与方法的一个形参名一致.
*/
//@AfterReturning(value="execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))",returning="result")
@AfterReturning(value="declarePointCut()",returning="result")
public void afterReturningMethod(JoinPoint joinPoint, Object result ) {
//方法的名字
String methodName = joinPoint.getSignature().getName();
System.out.println("LoggingAspect==> The method " + methodName + " end with :" + result );
}
/**
* 异常通知: 在目标方法抛出异常后执行.
*
* 获取方法的异常: 通过throwing来指定一个名字, 必须要与方法的一个形参名一致.
*
* 可以通过形参中异常的类型 来设置抛出指定异常才会执行异常通知.
*
*/
@AfterThrowing(value="execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))",throwing="ex")
public void afterThrowingMethod(JoinPoint joinPoint,ArithmeticException ex ) {
//方法的名字
String methodName = joinPoint.getSignature().getName();
System.out.println("LoggingAspect==> Thew method " + methodName + " occurs Exception: " +ex );
}
/**
* 环绕通知: 环绕着目标方法执行. 可以理解是 前置 后置 返回 异常 通知的结合体,更像是动态代理的整个过程.
*/
@Around("execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))")
public Object aroundMethod(ProceedingJoinPoint pjp) {
//执行目标方法
try {
//前置
Object result = pjp.proceed();
//返回
return result ;
} catch (Throwable e) {
//异常通知
e.printStackTrace();
}finally {
// 后置
}
return null;
}
}