五种通知
使用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>