前置通知
Posted zhzcode
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前置通知相关的知识,希望对你有一定的参考价值。
【Spring AOP】
1.AspectJ:Java社区里最完整最流行的AOP框架。
2.在Spring2.0 以上的版本中,可以使用基于AspectJ注解或基于XML配置的AOP。
【在Spring中启用AspectJ注解支持】
1.要在Spring应用中使用AspectJ注解,必须在classpath下包含AspectJ类库:aopalliance.jar、aspectj.weaver.jar和spring-aspects.jar。
2.将aop Schema添加到<beans>根元素中。
3.要在Spring IOC容器中启用AspectJ注解支持,只要在Bean配置文件中定义一个空的XML元素<aop:aspectj-autoproxy>。
4.当Spring IOC容器侦测到Bean配置文件中的<aop:aspectj-autoproxy>元素时,会自动为与AspectJ切面匹配的Bean创建代理。
【用AspectJ注解声明切面】
1.要在Spring中声明AspectJ切面,只需要在IOC容器中将切面声明为Bean实例。当在Spring IOC容器中初始化AspectJ切面之后,Spring IOC 容器就会为那些与AspectJ切面相匹配的Bean创建代理。
2.在AspectJ注解中,切面只是一个带有@Aspect注解的Java类。
3.通知是标注有某种注解的简单的Java方法。
4.AspectJ支持5种类型的通知注解:
--@Before:前置通知,在方法执行之前执行
--@After:后置通知,在方法执行之后执行
--@AfterRunning:返回通知,在方法返回结果之后执行
--@AfterThrowing:异常通知,在方法抛出异常之后
--@Around:环绕通知,围绕着方法执行
实现:在result结果输出前会有一个提示语句输出。
LoggingAspect.java:
1 package com.hk.spring.aop.impl; 2 3 import java.util.Arrays; 4 import java.util.List; 5 import org.aspectj.lang.JoinPoint; 6 import org.aspectj.lang.annotation.Aspect; 7 import org.aspectj.lang.annotation.Before; 8 import org.springframework.stereotype.Component; 9 10 //把这个类声明为一个切面。步骤:需要把该类放入到IOC容器中,然后再声明为一个切面。 11 @Aspect 12 @Component 13 public class LoggingAspect { 14 //声明该方法是一个前置通知:在目标方法之前执行 15 @Before("execution(public int com.hk.spring.aop.impl.ArithmeticCalculator.add(int,int))") 16 public void beforeMethod(JoinPoint joinPoint){ 17 String methodName = joinPoint.getSignature().getName(); 18 List<Object> args = Arrays.asList(joinPoint.getArgs()); 19 System.out.println("The method " + methodName + " begins with " + args); 20 } 21 }
applicationContext.xml:
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 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-4.3.xsd 10 http://www.springframework.org/schema/aop 11 http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"> 12 13 <!-- 配置自动扫描的包 --> 14 <context:component-scan base-package="com.hk.spring.aop.impl"></context:component-scan> 15 16 <!-- 使AspectJ 注解起作用:自动为匹配的类生成代理对象 --> 17 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 18 </beans>
Main.java:
1 package com.hk.spring.aop.impl; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 public class Main { 7 public static void main(String[] args) { 8 //1.创建Spring的IOC容器 9 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); 10 11 //2.从IOC容器中获取Bean的实例 12 ArithmeticCalculator arithmeticCalculator = ctx.getBean(ArithmeticCalculator.class); 13 //3.使用bean 14 int result = arithmeticCalculator.add(3, 6); 15 System.out.println("result:" + result); 16 } 17 18 }
运行结果:
假如在Main.java代码最后再加入:
1 result = arithmeticCalculator.div(12, 6); 2 System.out.println("result:" + result);
要使切面代码对该句也有效,需要在切面代码中把add改为*,否则不会有效,下图示:
注:如果不改动代码仍为add,那就是表明只对add方法有效。
【利用方法签名编写AspectJ切入点表达式】
1.最典型的切入点表达式是根据方法的签名来匹配各种方法
--execution * com.hk.spring.aop.impl.ArithmeticCalculator.*(..):匹配ArithmeticCalculator中声明的所有方法,第一个 “ * ” 代表任意修饰符以及任意返回值,第二个“ * ” 代表任意方法。“ .. ”匹配任意数量的参数。若目标类与接口与该切面在同一个包中,可以省略包名。
--execution public* ArithmeticCalculator.*(..):匹配ArithmeticCalculator接口的所有公有方法。
--execution public double ArithmeticCalculator.*(..):匹配ArithmeticCalculator中返回double类型数值的方法。
--execution public double ArithmeticCalculator.*(double,..):匹配第一个参数为double类型的方法,“ .. ” 匹配任意数量任意类型的参数。
--execution public double ArithmeticCalculator.*(double,double):匹配参数类型为 double,double 类型的方法。
运行结果:
【让通知访问当前连接点的细节】
可以在通知方法中声明一个类型为JoinPoint的参数。然后就能访问链接细节。如方法名称和参数值。
附:
小结:
1.Spring AOP
(1)加入jar包:
(2)在配置文件中加入AOP命名空间。
(3)基于注解的方式
①在配置文件中加入如下配置:
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
②把横切关注点的代码抽象到切面的类中。
(i)切面首先是一个IOC中的Bean,即加入 @Component 注解
(ii)切面还需要@Aspect 注解
③在类中声明各种通知:
(i)声明一个方法
(ii)在一个方法前加入@Before注解
④可以在通知方法中声明一个类型为JoinPoint的参数。然后就能访问链接细节。如方法名称和参数值。
1 //把这个类声明为一个切面。步骤:需要把该类放入到IOC容器中,然后再声明为一个切面。 2 @Aspect 3 @Component 4 public class LoggingAspect { 5 //声明该方法是一个前置通知:在目标方法之前执行 6 @Before("execution(public int com.hk.spring.aop.impl.ArithmeticCalculator.*(int,int))") 7 public void beforeMethod(JoinPoint joinPoint){ 8 String methodName = joinPoint.getSignature().getName(); 9 List<Object> args = Arrays.asList(joinPoint.getArgs()); 10 System.out.println("The method " + methodName + " begins with " + args); 11 }
以上是关于前置通知的主要内容,如果未能解决你的问题,请参考以下文章
Spring(十七):Spring AOP:通知(前置后置返回异常环绕)
[原创]java WEB学习笔记106:Spring学习---AOP的通知 :前置通知,后置通知,返回通知,异常通知,环绕通知