AOP(面向方面编程)是一种新的编程技术,它能够将那些本不应该纠缠在一起的任务分离开,从而为程序提供更好的封装性和互操作性.
AOP是通过代理机制实现的.
代理是指为其他对象提供一种代理以控制对这个对象的访问.
代理分为三种:
1.静态代理,代理对象必须实现目标对象的接口,且一个接口只服务于一种类型的目标对象。
2.JDK动态代理,代理对象必须实现java.lang.reflect.InvacationHandler接口,只能为接口创建代理实例。
3.CGLib动态代理,使用非常底层的字节码技术,可以为任何对象创建代理.
以下是目标对象接口和目标对象.
目标对象接口如下:
package org.test.spring.aop;
public interface IHello
{
public void hello(String name);
}
目标对象如下:
package org.test.spring.aop;
public class HelloSpeaker implements IHello
{
public void hello(String name)
{
System.out.print("Hi," + name);
}
}
一.静态代理
静态代理比较容易理解,静态代理其实很容易理解,静态代理其实就是个装饰器而已.
让代理对象也实现目标对像的接口,这样做的目的是让使用者在使用代理对象时感觉不到代理对象的存在.
代理对象如下:
package org.test.spring.aop;
public class HelloSpeakerProxy implements IHello
{
private IHello helloSpeaker;
public HelloSpeakerProxy(IHello helloSpeaker)
{
this.helloSpeaker = helloSpeaker;
}
public void hello(String name)
{
this.helloSpeaker.hello(name);
System.out.println(", welcome to our pub.");
}
public static void main(String[] args)
{
IHello helloSpeaker = new HelloSpeaker();
IHello proxy = new HelloSpeakerProxy(helloSpeaker);
proxy.hello("Huy Vanpon");
}
}
二.JDK动态代理
所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
package org.test.spring.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class HelloSpeakerProx implements InvocationHandler
{
private Object target;
public Object invoke(Object proxy, Method method, Object[] parameters)
throws Throwable
{
Object object = null;
try
{
object = method.invoke(target, parameters);
System.out.println(", welcome to our pub.");
}
catch (Exception e)
{
e.printStackTrace();
}
return object;
}
/**
* <p>
* 这个方法用于得到代理对象
* </p>
*
* @param target
* 目标对象
* @return result(Object)代理对象
*/
public Object getProxy(Object target)
{
this.target = target;
/**
* newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
* InvocationHandler invocationHandler) loader: 定义代理类的加加载器(目标类的加载器)
* interfaces: 代理类要实现的接口列表 invocationHandler: 指派方法调用的调用处理程序
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
public static void main(String[] args)
{
IHello proxy = (IHello) new HelloSpeakerProx()
.getProxy(new HelloSpeaker());
proxy.hello("Huy Vanpon");
}
}
三.CGLib动态代理
使用jdk创建代理有一个限制,即它只能为接口创建代理实例.CGLib使用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的拦截技术,并顺势织入横切逻辑.
运行这个例子,一定要记得导入CGLib相应的包哦..
package org.test.spring.aop;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class HelloSpeakerPro implements MethodInterceptor
{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz)
{
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object object, Method method, Object[] args,
MethodProxy proxy) throws Throwable
{
Object result = null;
result = proxy.invokeSuper(object, args);
System.out.println(", welcome to our pub.");
return result;
}
public static void main(String[] args)
{
HelloSpeakerPro helloSpeakerPro = new HelloSpeakerPro();
HelloSpeaker helloSpeaker = (HelloSpeaker) helloSpeakerPro
.getProxy(HelloSpeaker.class);
helloSpeaker.hello("Huy Vanpon");
}
}