五种通知
使用AspectJ注解声明切面
1)需要在spring IoC容器中将AspectJ切面声明为bean实例。
当Spring IOC容器初始化AspectJ切面后,spring IOC容器会为
AspectJ切面匹配的bean创建代理
2)在AspectJ注解中,切面是一个带有@Aspect注解的java类
3)通知是标识某种注解的简单Java方法
5中类型的通知注解
@Before前置通知,在方法执行之前执行
@After后置通知,在方法执行之后执行
@AfterRunning返回通知,在方法返回结果后执行
@AfterThrowing异常通知,在方法抛出异常之后
@Around环绕通知,围绕方法执行
4)使用@Order标识切面优先级,值越小优先级越高
依赖的jar包
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${org.spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency>
LoggingAspect.java
package com.hous.math;
import java.util.ArrayList;
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.mchange.v1.util.ArrayUtils;
/**
* 1.吧该类放到容器中 2.声明为一个切面
* 3.@Order切面优先级,值越小优先级越高
*/
@Order(2)
@Aspect
@Component
public class LoggingAspect {
/**
* 声明前置通知,在方法执行之前执行
* @param joinPoint
*/
@Before("execution(* com.hous.math.*.*(..))")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("the method " + methodName + " begin with " + args);
}
/**
* 后置通知,在目标方法执行后执行的通知(无论其是否发生异常)
* 后置通知不能访问目标方法执行的结果
* @param joinPoint
*/
@After("execution(* com.hous.math.*.*(..))")
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("the method " + methodName + " end with " + args);
}
/**
* 在方法正常执行结束执行的通知
* 可以访问到方法的返回值
* @param joinPoint
* @param result
*/
@AfterReturning(value="execution(* com.hous.math.*.*(..))",
returning="result")
public void afterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("the method " + methodName + " end with result " + result);
}
/**
* 在目标方法发生异常执行的代码
* 可以访问到异常对象,可以规定在某些特定异常执行
* @param joinPoint
* @param e
*/
@AfterThrowing(value="execution(* com.hous.math.*.*(..))",
throwing="e")
public void afterThrowing(JoinPoint joinPoint, ArithmeticException e) {
String methodName = joinPoint.getSignature().getName();
System.out.println("the method " + methodName + " occurs exception " + e);
}
/**
* @param pjd
* @return
*/
@Around("execution(* com.hous.math.*.*(..))")
public Object aroundMethod(ProceedingJoinPoint pjd) {
Object result = null;
String methodName = pjd.getSignature().getName();
try {
//前置通知
System.out.println("the methods " + methodName + " begins with" + Arrays.asList(pjd.getArgs()));
//执行目标方法
result = pjd.proceed();
//后置通知
System.out.println("the methods " + methodName + " ends with result " + result);
} catch (Throwable e) {
//异常通知
System.out.println("the methods " + methodName + " occurs exception" + e);
throw new RuntimeException(e);
}
//后置通知
System.out.println("the methods " + methodName + " ends");
return result;
}
}
xml配置
<?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:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <context:component-scan base-package="com.hous.math"> </context:component-scan> <!-- 为@Aspect标记,自动为匹配的类生成代理对象 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
重用切入点表达式
定义一个方法,声明切入点表达式。该方法不需要添加其他代码
在不同包下的引用需要加上包路径com.hous.LoggingAspect.declareJoinPointExpression()就这样
package com.hous.math;
import java.util.ArrayList;
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.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.mchange.v1.util.ArrayUtils;
/**
* 1.吧该类放到容器中 2.声明为一个切面
* @Order切面优先级,值越小优先级越高
*/
@Order(2)
@Aspect
@Component
public class LoggingAspect {
/**
* 定义一个方法,声明切入点表达式。该方法不需要添加其他代码
*/
@Pointcut("execution(* com.hous.math.*.*(..))")
public void declareJoinPointExpression() {}
/**
* 声明前置通知,在方法执行之前执行
* @param joinPoint
*/
@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 + " begin with " + args);
}
/**
* 后置通知,在目标方法执行后执行的通知(无论其是否发生异常)
* 后置通知不能访问目标方法执行的结果
* @param joinPoint
*/
@After("declareJoinPointExpression()")
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("the method " + methodName + " end with " + args);
}
/**
* 在方法正常执行结束执行的通知
* 可以访问到方法的返回值
* @param joinPoint
* @param result
*/
@AfterReturning(value="declareJoinPointExpression()",
returning="result")
public void afterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("the method " + methodName + " end with result " + result);
}
/**
* 在目标方法发生异常执行的代码
* 可以访问到异常对象,可以规定在某些特定异常执行
* @param joinPoint
* @param e
*/
@AfterThrowing(value="declareJoinPointExpression()",
throwing="e")
public void afterThrowing(JoinPoint joinPoint, ArithmeticException e) {
String methodName = joinPoint.getSignature().getName();
System.out.println("the method " + methodName + " occurs exception " + e);
}
/**
* @param pjd
* @return
*/
@Around("declareJoinPointExpression()")
public Object aroundMethod(ProceedingJoinPoint pjd) {
Object result = null;
String methodName = pjd.getSignature().getName();
try {
//前置通知
System.out.println("the methods " + methodName + " begins with" + Arrays.asList(pjd.getArgs()));
//执行目标方法
result = pjd.proceed();
//后置通知
System.out.println("the methods " + methodName + " ends with result " + result);
} catch (Throwable e) {
//异常通知
System.out.println("the methods " + methodName + " occurs exception" + e);
throw new RuntimeException(e);
}
//后置通知
System.out.println("the methods " + methodName + " ends");
return result;
}
}
使用配置文件方式配置AOP<?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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:component-scan base-package="com.hous.math">
</context:component-scan>
<!-- 配置AOP -->
<aop:config>
<!-- 配置切点表达式 -->
<aop:pointcut expression="execution(* com.hous.math.*.*(..))"
id="loggingPointcut"/>
<!-- 配置切面及通知 -->
<aop:aspect ref="loggingAspect2" order="1">
<!--
<aop:before method="beforeMethod" pointcut-ref="loggingPointcut" />
<aop:after method="afterMethod" pointcut-ref="loggingPointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="loggingPointcut" throwing="e"/>
<aop:after-returning method="afterReturning" pointcut-ref="loggingPointcut" returning="result"/>
-->
<aop:around method="aroundMethod" pointcut-ref="loggingPointcut"/>
</aop:aspect>
</aop:config>
</beans>