用 AspectJ 注解声明切面:
前置通知:
- 1 <?xml version="1.0" encoding="UTF-8"?>
- 2 <beans xmlns="http://www.springframework.org/schema/beans"
- 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- 4 xmlns:aop="http://www.springframework.org/schema/aop"
- 5 xmlns:context="http://www.springframework.org/schema/context"
- 6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- 7 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
- 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
- 9
- 10 <!-- IOC 扫描包 -->
- 11 <context:component-scan base-package="com.itdoc.spring.aop.impl"></context:component-scan>
- 12 <!-- 使 AspectJ 注解起作用, 自动为匹配的类生成代理对象 -->
- 13 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- 14
- 15 </beans>
注意:一定要添加 aop 命名空间。
- 1 package com.itdoc.spring.aop.impl;
- 2
- 3 import org.springframework.stereotype.Component;
- 4
- 5 /**
- 6 * http://www.cnblogs.com/goodcheap
- 7 *
- 8 * @author: Wáng Chéng Dá
- 9 * @create: 2017-03-03 19:34
- 10 */
- 11 @Component
- 12 public interface Arithmetic {
- 13
- 14 int add(int i, int j);
- 15
- 16 int sub(int i, int j);
- 17
- 18 int mul(int i, int j);
- 19
- 20 int div(int i, int j);
- 21
- 22 }
- 1 package com.itdoc.spring.aop.impl;
- 2
- 3 import org.springframework.stereotype.Component;
- 4
- 5 /**
- 6 * http://www.cnblogs.com/goodcheap
- 7 *
- 8 * @author: Wáng Chéng Dá
- 9 * @create: 2017-03-03 19:35
- 10 */
- 11 @Component("arithmetic")
- 12 public class ArithmeticImpl implements Arithmetic {
- 13 @Override
- 14 public int add(int i, int j) {
- 15 int result = i + j;
- 16 return result;
- 17 }
- 18
- 19 @Override
- 20 public int sub(int i, int j) {
- 21 int result = i - j;
- 22 return result;
- 23 }
- 24
- 25 @Override
- 26 public int mul(int i, int j) {
- 27 int result = i * j;
- 28 return result;
- 29 }
- 30
- 31 @Override
- 32 public int div(int i, int j) {
- 33 int result = i / j;
- 34 return result;
- 35 }
- 36 }
- 1 package com.itdoc.spring.aop.impl;
- 2
- 3
- 4 import org.aspectj.lang.JoinPoint;
- 5 import org.aspectj.lang.annotation.Aspect;
- 6 import org.aspectj.lang.annotation.Before;
- 7 import org.springframework.stereotype.Component;
- 8
- 9 import java.util.Arrays;
- 10
- 11 /**
- 12 * http://www.cnblogs.com/goodcheap
- 13 * 声明为一个切面的类: 需要把该类放到 IOC 容器中, 再声明为一个切面。
- 14 * @author: Wáng Chéng Dá
- 15 * @create: 2017-03-03 21:37
- 16 */
- 17 @Aspect
- 18 @Component
- 19 public class LoggingAspect {
- 20
- 21 //声明该方法为前置通知: 在目标方法执行之前开始执行。
- 22 @Before("execution(* com.itdoc.spring.aop.impl.*.*(..))")
- 23 public void beforeMethod(JoinPoint joinPoint) {
- 24 Object methodName = joinPoint.getSignature().getName();
- 25 Object args = Arrays.asList(joinPoint.getArgs());
- 26 System.out.println("The method " + methodName + " begins with " + args);
- 27 }
- 28 }
@Before("execution(* com.itdoc.spring.aop.impl.*.*(..))")
注意:在 AspectJ 中 , 切点表达式可以通过操作符 && , || , ! 结合起来。
- 1 package com.itdoc.spring.aop.impl;
- 2
- 3 import org.springframework.context.ApplicationContext;
- 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
- 5
- 6 /**
- 7 * http://www.cnblogs.com/goodcheap
- 8 *
- 9 * @author: Wáng Chéng Dá
- 10 * @create: 2017-03-03 21:32
- 11 */
- 12 public class Main {
- 13
- 14 public static void main(String[] args) {
- 15
- 16 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
- 17 Arithmetic arithmetic = (Arithmetic) ctx.getBean("arithmetic");
- 18 System.out.println("result = " + arithmetic.add(9, 5));
- 19 System.out.println("result = " + arithmetic.sub(9, 5));
- 20 }
- 21 }
控制台输出:
The method add begins with [9, 5] |
后置通知:
- 1 package com.itdoc.spring.aop.impl;
- 2
- 3
- 4 import org.aspectj.lang.JoinPoint;
- 5 import org.aspectj.lang.annotation.After;
- 6 import org.aspectj.lang.annotation.Aspect;
- 7 import org.aspectj.lang.annotation.Before;
- 8 import org.springframework.stereotype.Component;
- 9
- 10 import java.util.Arrays;
- 11
- 12 /**
- 13 * http://www.cnblogs.com/goodcheap
- 14 * 声明为一个切面的类: 需要把该类放到 IOC 容器中, 再声明为一个切面。
- 15 * @author: Wáng Chéng Dá
- 16 * @create: 2017-03-03 21:37
- 17 */
- 18 @Aspect
- 19 @Component
- 20 public class LoggingAspect {
- 21
- 22 //声明该方法为前置通知: 在目标方法执行之前开始执行。
- 23 @Before("execution(* com.itdoc.spring.aop.impl.*.*(..))")
- 24 public void beforeMethod(JoinPoint joinPoint) {
- 25 Object methodName = joinPoint.getSignature().getName();
- 26 Object args = Arrays.asList(joinPoint.getArgs());
- 27 System.out.println("The method " + methodName + " begins with " + args);
- 28 }
- 29
- 30 //声明该方法为后置通知: 在目标方法执行之后(无论是否发生异常)开始执行。
- 31 @After("execution(* com.itdoc.spring.aop.impl.*.*(..))")
- 32 public void afterMethod(JoinPoint joinPoint) {
- 33 Object methodName = joinPoint.getSignature().getName();
- 34 Object args = Arrays.asList(joinPoint.getArgs());
- 35 System.out.println("The method " + methodName + " ends with " + args);
- 36 }
- 37 }
- 1 package com.itdoc.spring.aop.impl;
- 2
- 3 import org.springframework.context.ApplicationContext;
- 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
- 5
- 6 /**
- 7 * http://www.cnblogs.com/goodcheap
- 8 *
- 9 * @author: Wáng Chéng Dá
- 10 * @create: 2017-03-03 21:32
- 11 */
- 12 public class Main {
- 13
- 14 public static void main(String[] args) {
- 15
- 16 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
- 17 Arithmetic arithmetic = (Arithmetic) ctx.getBean("arithmetic");
- 18 System.out.println("result = " + arithmetic.add(9, 5));
- 19 System.out.println("result = " + arithmetic.div(9, 0));
- 20 }
- 21 }
控制台输出:
Exception in thread "main" java.lang.ArithmeticException: / by zero |
返回通知:
无论连接点是正常返回还是抛出异常 , 后置通知都会执行。如果只想在连接点返回的时候记录日志 , 应使用返回通知代替后置通知。
- 1 package com.itdoc.spring.aop.circular;
- 2
- 3 import org.aspectj.lang.JoinPoint;
- 4 import org.aspectj.lang.annotation.AfterReturning;
- 5 import org.aspectj.lang.annotation.Aspect;
- 6 import org.springframework.stereotype.Component;
- 7
- 8 /**
- 9 * 通知
- 10 * http://www.cnblogs.com/goodcheap
- 11 *
- 12 * @author: Wáng Chéng Dá
- 13 * @create: 2017-03-04 9:50
- 14 */
- 15 @Aspect
- 16 @Component
- 17 public class AsjectLogging {
- 18
- 19 /**
- 20 * 在方法正常结束后执行代码。
- 21 * 返回通知是可以访问到方法的返回值的。
- 22 */
- 23 @AfterReturning(value = "execution(* com.itdoc.spring.aop.circular.*.*(..))", returning = "result")
- 24 public void afterReturning(JoinPoint joinPoint, Object result) {
- 25 Object methodName = joinPoint.getSignature().getName();
- 26 System.out.println("The method " + methodName + " ends with " + result);
- 27 }
- 28 }
异常通知:
- 1 package com.itdoc.spring.aop.circular;
- 2
- 3 import org.aspectj.lang.JoinPoint;
- 4 import org.aspectj.lang.annotation.AfterReturning;
- 5 import org.aspectj.lang.annotation.AfterThrowing;
- 6 import org.aspectj.lang.annotation.Aspect;
- 7 import org.springframework.stereotype.Component;
- 8
- 9 /**
- 10 * 通知
- 11 * http://www.cnblogs.com/goodcheap
- 12 *
- 13 * @author: Wáng Chéng Dá
- 14 * @create: 2017-03-04 9:50
- 15 */
- 16 @Aspect
- 17 @Component
- 18 public class AsjectLogging {
- 19
- 20 /**
- 21 * 在目标方法出现异常时候执行的代码。
- 22 * 可以访问到异常对象, 且可以指定在出现特定异常时再执行的代码。
- 23 */
- 24 @AfterThrowing(value = "execution(* com.itdoc.spring.aop.circular.*.*(..))", throwing = "e")
- 25 public void afterThrowing(JoinPoint joinPoint, Exception e) {
- 26 Object methodName = joinPoint.getSignature().getName();
- 27 System.out.println("The method " + methodName + " exception with " + e);
- 28 }
- 29 }
环绕通知:
- 1 package com.itdoc.spring.aop.circular;
- 2 3 import org.aspectj.lang.ProceedingJoinPoint;
- 4 import org.aspectj.lang.annotation.Around;
- 5 import org.aspectj.lang.annotation.Aspect;
- 6 import org.springframework.stereotype.Component;
- 7 8 import java.util.Arrays;
- 9 10
- /**
- 11 * 通知
- 12 * http://www.cnblogs.com/goodcheap
- 13 *
- 14 * @author: Wáng Chéng Dá
- 15 * @create: 2017-03-04 9:50
- 16 */
- 17@Aspect 18@Component 19 public class AsjectLogging {
- 20 21
- /**
- 22 * 环绕通知需携带 ProceedingJoinPoint 类型的参数。
- 23 * 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型参数可以决定是否执行目标方法。
- 24 * 环绕通知必须有返回值, 返回值即目标方法的返回值。
- 25 *
- 26 * @param point
- 27 * @return
- 28 */
- 29@Around("execution(* com.itdoc.spring.aop.circular.*.*(..))") 30 public Object around(ProceedingJoinPoint point) {
- 31 Object methodName = point.getSignature().getName();
- 32 Object[] args = point.getArgs();
- 33 Object result = null;
- 34
- try {
- 35 //前置通知
- 36 System.out.println("The method " + methodName + " begins with" + Arrays.asList(args));
- 37 //执行方法
- 38 result = point.proceed();
- 39 //返回通知
- 40 System.out.println("The method " + methodName + " ends with " + result);
- 41
- } catch(Throwable e) {
- 42 e.printStackTrace();
- 43 //异常通知
- 44 System.out.println("The method " + methodName + " exception with " + e);
- 45
- } finally {
- 46 //后置通知
- 47 System.out.println("The method " + methodName + " ends");
- 48
- }
- 49
- return result;
- 50
- }
- 51
- }
来源: http://www.bubuko.com/infodetail-1968122.html