1,概述:
AOP(Aspect Orient Programming),面向切面编程,是面向对象编程的一种补充。面向对象编程是从静态角度考虑程序的结构,而面向切面编程是从动态角度考虑程序运行过程。面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP容器的功能将切面织入到主业务逻辑中。所谓交叉业务逻辑是指,通用的、与主业务逻辑无关的代码,如安全检查、事务、日志等。
2,涉及概念:
(1)切面(Aspect) :泛指交叉业务逻辑。常用的切面有通知与顾问。
(2)织入(Weaving):将切面代码插入到目标对象的过程。
(3)通知(Advice):切面的一种实现,可以完成简单织入功能。
(4)切入点(Pointcut):表示切面具体织入的位置。
(5)顾问(Advisor):切面的一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。
(6)引入(Introduction):特殊的通知,可以动态的给目标类增加新的属性和方法,而不用修改目标类的源代码。
(7)目标对象(Target):也称为委托对象,被通知对象。
(8) AOP代理对象(AOP Proxy): 代理对象=目标对象+交叉业务逻辑。
3,通知:advice:
通知(Advice)分四大类:前置通知、后置通知、 环绕通知、异常处理通知。对于它们的配置与使用,大体分为以下步骤:
(1)配置目标对象
(2)配置通知
(3)配置代理对象,完成织入。完成织入进行配置时,由于是通过ProxyFactoryBean将通知织入到目标对象,形成一个动态代理对象的,所以我们在客户端所使用的对象应为此代理对象,即这里的bean的id。该代理对象Bean的class为下面的类:org.springframework.aop.framework.ProxyFactoryBean。该Bean的属性需配置如下几项:
<property name=“proxyInterfaces” value=“接口全路径" />设置目标对象所实现的业务接口,要求给出全名。如果目标对象没有实现业务接口,则可以不设置。name属性名只能用proxyInterfaces 。
<property name=“target” ref=“目标对象Bean的id" />指定目标对象,name属性名只能用target 。
(4)客户端访问的是动态代理对象
若有多个通知要织入,则使用如下形式:
<property name="interceptorNames">
<list>
<value>通知1的id </value>
<value>通知2的id </value>
<value>……</value>
</list>
</property>
3.1前置通知---MethodBeforeAdvice
该接口中有一个方法:public void before ( Method targetMethod, Object[] args, Object target)
该方法会在目标方法执行之前执行,其有三个参数: targetMethod:目标方法 args:目标方法的参数target:目标对象
前置通知的特点:
在目标方法执行之前先执行。
不改变目标方法的执行流程,前置通知代码不能阻止目标方法执行。
不改变目标方法执行的结果。
3.2,后置通知---AfterReturningAdvice
该接口中有一个方法public void afterReturning ( Object returnValue, Method targetMethod, Object[] args, Object target)该方法会在目标方法执行之后执行,其有四个参数:returnValue:目标方法的返回值 targetMethod:目标方法 args:目标方法的参数 target:目标对象
后置通知的特点:
在目标方法执行之后执行。
不改变目标方法的执行流程,后置通知代码不能阻止目标方法执行。
不改变目标方法执行的结果。
3.3:环绕通知---MethodInterceptor
环绕通知,也叫方法拦截器,可以在目标方法调用之前及之后做处理,可以改变目标方法的返回值,也可以改变程序执行流程。
这个接口中有一个方法:public Object invoke ( MethodInvocation mi)MethodInvocation接口对象可以描述带有任意参数的任意方法的调用,该接口由容器负责实现。该接口对象有一个方法proceed(),用于调用执行由其所描述的方法。invoke()方法是由容器调用的,所以,不用程序员显式调用。
方法拦截器的特点:
在目标方法执行之前及之后都会执行。
可以改变目标方法的执行流程。
可以改变目标方法执行的结果。
3.4,异常通知---ThrowsAdvice
该接口的主要作用是,在目标方法抛出异常后,根据异常的不同做出相应的处理。当该接口处理完异常后,会简单地将异常再次抛出给目标方法。
不过,这个接口较为特殊,从形式上看,该接口中没有必须要实现的方法。但,这个接口却确实有必须要实现的方法afterThrowing()。这个方法重载了四种形式。由于使用时,一般只使用其中一种,若要都定义到接口中,则势必要使程序员在使用时必须要实现这四个方法。这是很麻烦的。所以就将该接口定义为了标识接口(没有方法的接口)。
在这四种形式中,常用的有两种形式:public void afterThrowing(自定义的异常类 e)public void afterThrowing(Method targetMethod, Object[] args, Object target,自定义的异常类 e)。
4,给目标方法织入多个切面
若要给目标方法织入多个切面,则需要在配置代理对象的切面属性时,设定为list。
<property name="interceptorNames">
<list>
<value>before</value>
<value>after</value>
</list>
</property>
给目标方法织入多个切面具体步骤:
(1)定义接口
(2)定义实现类
(3)定义前置通知
(4)定义后置通知
(5)修改配置文件
(6)定义客户类