什么是AOP:
假设我们把业务类看成一段圆木,将业务方法看成截断圆木的最内层的年轮,对最内层代码的修饰是外面层层包裹的外部年轮,这就是是横切代码的由来。
AOP希望将分散在各个业务逻辑代码中的相同代码通过横向切割的方式抽取到一个独立的模块中,还业务逻辑一个清新的世界。
AOP术语:
连接点:程序执行的某个特定的位置:类初始化前、类初始化后、类某个方法调用前、类某个方法调用后、方法抛出异常后。一个类或者一段程序>代码拥有一些具有边界性质的特定点就是连接点。
切点:每个程序类中由许多连接点,AOP通过“切点”定位特定连接点。一个切点对应多个连接点。
增强:增强是织入目标类连接点上的一段程序代码。
目标对象:增强逻辑的织入目标类
引介:引介是特殊的增强,用来为类添加一些属性和方法。
织入:织入是将增强添加到目标类具体连接点上的过程。
代理:一个类被AOP织入增强后,就产生一个结果类,它融入了原类和增强逻辑的代理类。
切面:切面是由切点和增强(引介)组成,它既包括了横切逻辑的定义,也包含了连接点的定义,Spring AOP就是负责实施切面的框架,它将切面>定义的横切逻辑织入到切面指定的连接点中。
Spring AOP使用两种代理机制:一种是基于JDK的动态代理,另一种是基于CGLib的动态代理。之所以用两种代理机制是因为:很大程度上JDK本身只提供接口的代理,
而不支持类的代理。
JDK动态代理:
主要涉及java.lang.reflect包中的两个类:Proxy和InvocationHandler.其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,
并且通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。
CGLib采用字节码技术,可以为一个类创建一个子类,并在子类中采用方法拦截技术拦截所有父类方法的调用,并顺势织入横切逻辑
创建增强类:
Spring使用增强类定义横切逻辑,同时由于Spring只支持方法连接点,增强还包括了在方法的哪一点加入横切代码的方位信息,还包括部分连接点的信息。
Spring支持五种增强接口:
前置增强
后置增强
环绕增强
异常抛出增强
引介增强
这些增强接口都有一些方法,通过实现这些接口方法,在接口方法中定义横切逻辑就可以将他们织入到目标类方法的相应连接点位置。
前置增强:
保证使用礼貌用语的实例:
具体实施:
ProxyFactory内部就是使用JDK或CGLib代理的技术,将增强应用到目标类中。我们可以通ProxyFactory的setInstance(Class[] interfaces)指定针
对接口进行代理,ProxyFactory就是使用JdkDynamicAopProxy;如果针对类的代理则使用Cglib2AopProxy。
我们还可以使用Spring的配置以“很Spring方式”声明一个代理:
后置增强:
假设我们把业务类看成一段圆木,将业务方法看成截断圆木的最内层的年轮,对最内层代码的修饰是外面层层包裹的外部年轮,这就是是横切代码的由来。
AOP希望将分散在各个业务逻辑代码中的相同代码通过横向切割的方式抽取到一个独立的模块中,还业务逻辑一个清新的世界。
AOP术语:
连接点:程序执行的某个特定的位置:类初始化前、类初始化后、类某个方法调用前、类某个方法调用后、方法抛出异常后。一个类或者一段程序>代码拥有一些具有边界性质的特定点就是连接点。
切点:每个程序类中由许多连接点,AOP通过“切点”定位特定连接点。一个切点对应多个连接点。
增强:增强是织入目标类连接点上的一段程序代码。
目标对象:增强逻辑的织入目标类
引介:引介是特殊的增强,用来为类添加一些属性和方法。
织入:织入是将增强添加到目标类具体连接点上的过程。
代理:一个类被AOP织入增强后,就产生一个结果类,它融入了原类和增强逻辑的代理类。
切面:切面是由切点和增强(引介)组成,它既包括了横切逻辑的定义,也包含了连接点的定义,Spring AOP就是负责实施切面的框架,它将切面>定义的横切逻辑织入到切面指定的连接点中。
Spring AOP使用两种代理机制:一种是基于JDK的动态代理,另一种是基于CGLib的动态代理。之所以用两种代理机制是因为:很大程度上JDK本身只提供接口的代理,
而不支持类的代理。
JDK动态代理:
主要涉及java.lang.reflect包中的两个类:Proxy和InvocationHandler.其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,
并且通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。
CGLib采用字节码技术,可以为一个类创建一个子类,并在子类中采用方法拦截技术拦截所有父类方法的调用,并顺势织入横切逻辑
创建增强类:
Spring使用增强类定义横切逻辑,同时由于Spring只支持方法连接点,增强还包括了在方法的哪一点加入横切代码的方位信息,还包括部分连接点的信息。
Spring支持五种增强接口:
前置增强
后置增强
环绕增强
异常抛出增强
引介增强
这些增强接口都有一些方法,通过实现这些接口方法,在接口方法中定义横切逻辑就可以将他们织入到目标类方法的相应连接点位置。
前置增强:
保证使用礼貌用语的实例:
package com.baobaotao.advice;
public interface Waiter{
void greetTo(String name);
void serveTo(String name);
}
现在我们来看一个训练不足的服务生的服务情况:
package com.baobaotao.advice;
public class NaiveWaiter implements Waiter{
public void greerTo(String name){
System.out.println("greet to"+name+"..");
}
public void serveTo(String name){
System.out.println("serving"+name+"...");
}
}
构建增强:
package com.baobaotao.advice;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class GreetingBeforeAdvice implements MethodBeforeAdvice{
public void before(Method method,Object[] args,Object obj)throws Throwable{
String clilentName=(String)args[0];
System.out.println("How arg you! Mr."+clientName)+".");
}
}
注意:before(Method method,Object[] args,Object obj)throws Throwable中method 为目标类的方法,args是目标类方法的入参,而obj是目标类实例。>当该方法发生异常时,将阻止目标类方法的执行。
具体实施:
package com.baobaotao.advice;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
public class TestBeforeAdvice{
public static void main(String[] args){
Waiter target=new NaiveWaiter();
BeforeAdvice advice=new GreetingBeforeAdvice();
ProxyFactory pf=new ProxyFactory();
pf.setTarget(target);
pf.addAdvice(advice);
Waiter proxy=(Waiter)pf.getProxy();
proxy.greetTo("john");
proxy.serveTo("Tom");
}
}
ProxyFactory:
ProxyFactory内部就是使用JDK或CGLib代理的技术,将增强应用到目标类中。我们可以通ProxyFactory的setInstance(Class[] interfaces)指定针
对接口进行代理,ProxyFactory就是使用JdkDynamicAopProxy;如果针对类的代理则使用Cglib2AopProxy。
我们还可以使用Spring的配置以“很Spring方式”声明一个代理:
<bean id="greetingAdvice" class="com.baobaotao.advice.GreetingBeforeAdvice"/>
<bean id="target" class="com.baobaotao.advice.NaviWaiter"/>
<bean id="waiter" class="org.springframework.aop.framework.PorxyFactoryBean" p:proxyInterfaces="com.baobaotao.advice.Waiter" p:interceptorNames="greetingAdvice" p:target-ref="target"/>
后置增强:
package com.baobaotao.advice;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class GreetingAfterAdvice implements AfterReturningAdvice{
public void afterReturning(Object returnObj,Method method,Object[] args,Object obj)throws Throwable{
System.out.println("Please enjoy youself!");
}
}
环绕增强:
package com.baobatao.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class GreetingInterceptorimplements MethodInterceptor{
public Object invoke(MethodInvocation invokecation)throws Throwable{
Object[] args=invocation.getArguments();
String clientName=(String)args[0];
System.out.println("How are you! Mr."+clientName+".");
Object obj=invocation.proceed();
System.out.println("Please enjoy yourself!");
return obj;
}
}