标签:
参考代码下载github:https://github.com/changwensir/java-ee/tree/master/spring4
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: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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="Spring4_AOP.aopAnnotation"/> <!--使AspectJ注解起作用:自动为匹配的类生成代理对象--> <aop:aspectj-autoproxy/> </beans>ArithmeticCalculatorImpl在参见一篇博客http://blog.csdn.net/ochangwen/article/details/52557459
日志切面
* 4. 编写切面类(把横切关注点的代码抽象到切面的类中):
* 4.1 一个一般的 Java 类
* 4.2 在其中添加要额外实现的功能.
*
* 5. 配置切面
* 5.1 切面必须是 IOC 中的 bean: 实际添加了 @Component 注解
* 5.2 声明是一个切面: 添加 @Aspect
* 5.3 声明通知: 即额外加入功能对应的方法!!.
@Aspect @Component public class LoggingAspect { /** * 重用切入点定义 * 定义一个方法,用于声明切入点表达式,一般地,该方法中再不需要添入其它的代码 */ @Pointcut("execution(* Spring4_AOP.aopAnnotation.*.*(..))") public void declareJoinPointerExpression() {} //1、前置通知: 在目标方法开始之前执行(就是要告诉该方法要在哪个类哪个方法前执行) //@Before("execution(public int Spring4_AOP.aopAnnotation.*.*(int ,int))") @Before("declareJoinPointerExpression()") public void beforeMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); Object [] args = joinPoint.getArgs(); System.out.println("The method " + methodName + " begins with " + Arrays.asList(args)); } //2、后置通知:在目标方法执行后(无论是否发生异常),执行的通知 //注意,在后置通知中还不能访问目标执行的结果!!!,执行结果需要到返回通知里访问 //@After("execution(* Spring4_AOP.aopAnnotation.*.*(..))") @After("declareJoinPointerExpression()") public void afterMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " ends"); } //无论连接点是正常返回还是抛出异常, 后置通知都会执行. 如果只想在连接点返回的时候记录日志, 应使用返回通知代替后置通知. //3、返回通知:在方法正常结束后执行的代码,返回通知是可以访问到方法的返回值的!!! //@AfterReturning(pointcut = "execution(* Spring4_AOP.aopAnnotation.*.*(..))", returning = "result") @AfterReturning(value = "declareJoinPointerExpression()", returning = "result") public void afterReturning(JoinPoint joinPoint, Object result){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " AfterReturning ends with " + result); } //4、异常通知:在目标方法出现异常 时会执行的代码,可以访问到异常对象:且可以!!指定在出现特定异常时在执行通知!!,如果是修改为nullPointerException里,只有空指针异常才会执行 // @AfterThrowing(pointcut = "execution(* Spring4_AOP.aopAnnotation.*.*(..))", throwing = "except") @AfterThrowing(value = "declareJoinPointerExpression())", throwing = "except") public void afterThrowing(JoinPoint joinPoint, Exception except){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " occurs exception " + except); } /** * 5、环绕通知 需要携带 ProceedingJoinPoint 类型的参数. * 环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法. * 且环绕通知必须有返回值, 返回值即为目标方法的返回值 */ // @Around("execution(* Spring4_AOP.aopAnnotation.*.*(..))") @Around("declareJoinPointerExpression()") 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 + " ends with " + result); } catch (Throwable e) { //异常通知 System.out.println("The method " + methodName + " occurs exception:" + e); throw new RuntimeException(e); } //后置通知 System.out.println("The method " + methodName + " ends"); return result; } }注意:
@Pointcut("execution(* Spring4_AOP.aopAnnotation.*.add(..)) ||execution(* Spring4_AOP.aopAnnotation.*.sub(..))") public void declareJoinPointerExpression() {}返回通知:?无论连接点是正常返回还是抛出异常,后置通知都会执行.如果只想在连接点返回的时候记录日志,应使用返回通知代替后置通知.
3).环绕通知
@Test public void testAOPAnnotation() { //1、创建Spring的IOC的容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_AOP/applicationContext-aop.xml"); //2、从IOC容器中获取bean的实例 ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator"); //3、使用bean int result = arithmeticCalculator.div(3, 1); System.out.println("result:" + result); }
@Order(1) @Aspect @Component public class ValidationAspect { @Before("execution(public int Spring4_AOP.aopAnnotation.*.*(int ,int))") public void validateArgs(JoinPoint joinPoint){ System.out.println("-->validate:" + Arrays.asList(joinPoint.getArgs())); } }日志切面,使用上面的那个类,只增加Order
@Order(2) @Aspect @Component public class LoggingAspect { ...... }
ArithmeticCalulator2与上面ArithmeticCalulator接口内容 一样
public class ArithmeticCalculatorImplXML implements ArithmeticCalculator2 { public int add(int i, int j) { return i + j; } public int sub(int i, int j) { return i - j; } public int mul(int i, int j) { return i * j; } public int div(int i, int j) { return i / j; } }
public class LoggingAspectXML { public void beforeMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); Object [] args = joinPoint.getArgs(); System.out.println("The method " + methodName + " begins with " + Arrays.asList(args)); } public void afterMethod(JoinPoint joinPoint){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " ends"); } public void afterReturning(JoinPoint joinPoint, Object result){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " ends with " + result); } public void afterThrowing(JoinPoint joinPoint, Exception e){ String methodName = joinPoint.getSignature().getName(); System.out.println("The method " + methodName + " occurs excetion:" + e); } }
public class ValidationAspectXML { public void validateArgs(JoinPoint joinPoint){ System.out.println("-->validate:" + Arrays.asList(joinPoint.getArgs())); } }
<?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: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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 配置 bean --> <bean id="arithmeticCalculatorXML" class="Spring4_AOP.aopXML.ArithmeticCalculatorImplXML"> </bean> <!-- 配置切面的 bean. --> <bean id="loggingAspect" class="Spring4_AOP.aopXML.LoggingAspectXML"> </bean> <bean id="validationAspect" class="Spring4_AOP.aopXML.ValidationAspectXML"> </bean> <!-- 配置 AOP --> <aop:config> <!-- 配置切点表达式 --> <aop:pointcut id="pointcut" expression="execution(* Spring4_AOP.aopXML.ArithmeticCalculatorImplXML.*(int ,int))"/> <!-- 配置切面及通知 --> <aop:aspect ref="loggingAspect" order="2"> <aop:before method="beforeMethod" pointcut-ref="pointcut"/> <aop:after method="afterMethod" pointcut-ref="pointcut"/> <aop:after-returning method="afterReturning" returning="result" pointcut-ref="pointcut"/> <aop:after-throwing method="afterThrowing" throwing="e" pointcut-ref="pointcut"/> </aop:aspect> <aop:aspect ref="validationAspect" order="1"> <aop:before method="validateArgs" pointcut-ref="pointcut"/> </aop:aspect> </aop:config> </beans>
@Test public void testXML() { //1、创建Spring的IOC的容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring4_AOP/applicationContext-xml.xml"); //2、从IOC容器中获取bean的实例 ArithmeticCalculatorImplXML arithmeticCalculator = (ArithmeticCalculatorImplXML) ctx.getBean("arithmeticCalculatorXML"); //3、使用bean int result = arithmeticCalculator.add(3, 3); System.out.println("result:" + result); arithmeticCalculator.div(10, 0); }
Spring4深入理解AOP02----AOP简介,AspectJ基于注解(5种通知,切面优先级)
标签:
原文地址:http://blog.csdn.net/ochangwen/article/details/52557724