spring-aop学习笔记
来源:互联网 发布:数据有效性输入空格 编辑:程序博客网 时间:2024/04/29 23:45
一 基本概念
通知(Advice):切面的工作被称为通知。定义了切面是什么以及何时使用。spring切面可以应用5种类型的通知(Before、After、After-retrunning,After-throwing, Around)。
连接点(JointPoint):是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。
切点(Pointcut):切点定义了切面在何处。切点的定义会匹配通知所要织入的一个或多个连接点,我们通常使用明确的类和方法名称指定这些切点,或者利用正则表达式定义匹配的类和方法名称模式来指定这些切点。
切面(Aspect): 是通知和切点的结合,通知和切点共同定义了切面的全部内容——它是什么,在何时和何处完成其功能。
引入(introduction):允许我们向现有的类添加新方法或属性。
织入(Weaving): 将切面应用到目标对象来创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以织入。(编译器、类加载期、运行期)
二 基于xml配置的使用
目标类:
public interface IHelloWorldService { public void sayHello();}
public class HelloWorldService implements IHelloWorldService { @Override public void sayHello() { System.out.println("say hello"); }}
切面类:
public class HelloWorldAspect { //前置通知 public void beforAdvice(){ System.out.println("====before====="); } //后置通过 public void afterFinallyAdvice(){ System.out.println("====after===="); }}
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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id = "helloWorldService" class="aopTest.HelloWorldService"/> <bean id="aspect" class="aopTest.HelloWorldAspect"/> <aop:config> <aop:pointcut id="pointcut" expression="execution(* aopTest..*.*(..))"/> <aop:aspect ref="aspect"> <aop:before pointcut-ref="pointcut" method="beforAdvice"/> <aop:after pointcut-ref="pointcut" method="afterFinallyAdvice"/> </aop:aspect> </aop:config></beans>
<aop:config>用户配置aop
<aop:pointcut> 定义切点
<aop:aspect> 定义切面,其中ref用来引用切面支持类的bean。
<aop:before>前置通知 pointcut-ref 切点,引用在前面定义的切点,也可以直接使用pointcut定义一个匿名切点。mehthod 引用切换通知实现类中的方法,即在目标类方法执行之前调用的方法。
<aop:after>后置通知
测试类:
public class AopTest { @Test public void test(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop/spring-aop.xml"); IHelloWorldService helloWorldService = applicationContext.getBean(IHelloWorldService.class); helloWorldService.sayHello(); }}
输出结果:
====before=====
say hello
====after====
调试时,也可以看到helloWorldService类被spring代理了。
如果是有入参的方法,可以使用如下方式定义:
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!--<aop:aspectj-autoproxy/>--> <bean id = "helloWorldService" class="aopTest.HelloWorldService"/> <bean id="aspect" class="aopTest.HelloWorldAspect"/> <aop:config> <aop:pointcut id="pointcut" expression="execution(* aopTest..*.*(..)) and args(param)"/> <aop:aspect ref="aspect"> <aop:before pointcut-ref="pointcut" method="beforAdvice" arg-names="param"/> <aop:after pointcut-ref="pointcut" method="afterFinallyAdvice" arg-names="param"/> </aop:aspect> </aop:config></beans>其中需要注意的是
(1) pointCut中的expression中必须包含 args(param),否则会在运行时报错:0 formal unbound in pointcut
args是在用于匹配当前执行的方法传入的参数为指定类型的执行方法,是在运行时切入的,属于动态切入。
(2) 如果pointCut中包含 args(param), 则before和after通知的方法也必须包含该参数。
(3) before和after通知中arg-names可以省略不写。
(4) 可以通过order字段配置通知的优先级。order字段值越大,优先级越高。
<aop:config> <aop:pointcut id="pointcut" expression="execution(* aopTest..*.*(..)) and args(param)"/> <aop:aspect ref="aspect" order="2"> ...... </aop:aspect> </aop:config>
三 基于注解的使用
Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:
<aop:aspectj-autoproxy/>
切面类:
@Aspectpublic class HelloWorldAspect2 { @Pointcut(value = "execution(* aopTest..*.*(..))") public void pointTest(){}; @Before(value = "pointTest()") public void before(){ System.out.println("====before==="); }}
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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id = "helloWorldService" class="aopTest.HelloWorldService"/> <bean id = "aspect2" class="aopTest.HelloWorldAspect2"/></beans>
测试类:
public class AopTest { @Test public void test(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop/spring-aop.xml"); IHelloWorldService helloWorldService = applicationContext.getBean(IHelloWorldService.class); helloWorldService.sayHello(); }}
如果是有入参的方法,可以使用如下方式定义:
@Aspectpublic class HelloWorldAspect2 { @Pointcut(value = "execution(* aopTest..*.*(..)) && args(arg)") public void pointTest(String arg){}; @Before(value = "pointTest(arg)") public void before(String arg){ System.out.println("====before === + " + arg); }}
可以通过order字段制定通知的优先级:
@Aspect@Order(1)public class HelloWorldAspect2 { .....}
四 其他
aspectJ语法:http://www.importnew.com/17828.html
AspectJ类型匹配的通配符:
* : 匹配任何数量字符
.. : (两个点)匹配任何数量字符的重复。如在类型模式中匹配任何数量子包,而在方法参数模式中匹配任何数量参数
+:匹配执行类型的子类型,仅能作为后缀放在类型模式后边。
java.*.String: 匹配Java包下任何的一级子包的下的String类型,匹配java.lang.String,但不匹配java.lang.ss.String
java..* 匹配java包以及任何子包下的任何类型。匹配java.lang.String,java.lang.ss.String
采用JoinPoint传递参数:
使用方法非常简单,直接在通知方法中增加一个入参,需要注意的是,该入参需要放在第一个位置。
public void beforAdvice(JoinPoint joinPoint,String param){ System.out.println("====beforeAdvice=====" + param); }
其中JoinPoint有几个属性,getTarget()——获取目标对象
getThis()——获取代理对象,getArgs()——获取被通知对象的入参列表
Spring AOP通过代理模式实现,目前支持两种代理:JDK动态代理、CGLIB代理来创建AOP代理,Spring建议优先使用JDK动态代理.
要采用cglib代码:
对于xml配置的切面:
<aop:config proxy-target-class="true"> </aop:config>
对于基于@Aspect注解的切面:
<aop:aspectj-autoproxy proxy-target-class="true"/>
参考资料: http://www.importnew.com/17828.html
http://www.importnew.com/17813.html
http://www.importnew.com/17755.html
- Spring AOP学习笔记
- Spring AOP学习笔记
- Spring AOP学习笔记
- Spring AOP学习笔记
- Spring AOP学习笔记
- spring aop学习笔记
- spring aop学习笔记
- Spring AOP学习笔记
- spring AOP 学习笔记
- spring AOP学习笔记
- Spring AOP学习笔记
- Spring AOP学习笔记
- spring AOP 学习笔记
- Spring Aop 学习笔记
- spring aop学习笔记
- Spring-AOP学习笔记
- spring-aop学习笔记
- Spring AOP 学习笔记
- Linux /dev 自动创建设备节点
- 13、发布项目到私服
- javascript Date()
- Go语言内存分配器的实现
- 3123: [Sdoi2013]森林 主席树+启发式合并+LCA
- spring-aop学习笔记
- Android 判断SD卡是否存在及容量查询
- 1095. Cars on Campus (30)
- Go语言内存分配器-FixAlloc
- PHP http_response_code Get or Set the HTTP response code
- android 开发技巧(1)--使用 weight 属性实现视图的居中显示
- Go语言内存分配器-MSpan
- c++笔试题总结1
- Andoid 调用相机程序获取图片