您的位置:首页 > 编程语言 > Java开发

JDK和CGLib两种方式实现动态代理模式

2014-11-11 20:44 791 查看
这篇文章主要介绍利用JDK和cgLib两种方式实现动态代理模式的实例。

1. 利用JDK中的类

在JDK中的动态代理用到了两个类:Proxy和InvocationHandler,如下:



1.1 抽象主题

抽象主题的Java代码如下:

public interface Hello {
void sayHello(String to);
void print(String p);
}


1.2 实际主题

实际主题的Java代码如下:

public class HelloImpl implements Hello {
@Override
public void sayHello(String to) {
System.out.println("Say Hello to " + to);
}
@Override
public void print(String p) {
System.out.println("print : " + p);
}
}


1.3 代理

代理要实现的功能为:在sayHello()和print()两个方法前后加了Log日志。代理类的代码如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class LogHandler implements InvocationHandler {
private Object dele; //被代理对象传进来了

public LogHandler(Object obj) {
this.dele = obj;
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
doBefore();
// 在这里完全可以把下面这句注释掉,而做一些其它的事情
Object result = method.invoke(dele, args);
doAfter();
return result;
}

private void doBefore() {
System.out.println("before....");
}

private void doAfter() {
System.out.println("after....");
}
}


1.4测试运行

import java.lang.reflect.Proxy;

public class ProxyTest {
public static void main(String[] args) {
Hello impl = new HelloImpl();
LogHandler handler = new LogHandler(impl);
// 这里把handler与impl新生成的代理类相关联
Hello hello = (Hello) Proxy.newProxyInstance(
impl.getClass().getClassLoader(),
impl.getClass().getInterfaces(), handler);

// 这里无论访问哪个方法,都是会把请求转发到handler.invoke
hello.print("All the test");
hello.sayHello("Denny");
}
}


其运行结果如下:



这样,通过动态代理,就成功的在sayHello()和print()两个方法前后加了Log日志。

2. 利用cgLib中的类

下面这个例子展现了利用cgLib实现对ArrayList进行拦截,在在add或addAll元素的之前,会实行拦截操作,执行相关操作后再添加到ArrayList中去。

2.1 代理(拦截器)

import java.lang.reflect.Method;
import java.util.List;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 利用cglib的动态代理方法。java.util.List的拦截器,在add或addAll元素的之前,
* 会实行拦截操作, 执行相关操作后再添加到ArrayList中去。<br>
*/
public class ListAddMethodInterceptor implements MethodInterceptor {
@Override
@SuppressWarnings("unchecked")
public Object intercept(Object object, Method method,
Object[] args, MethodProxy methodProxy)
throws Throwable {
//函数体的执行
if(args != null && args.length >= 1) {
if(method.getName().equals("add")) { //add方法
addedThing = (T) args[0]; //被添加的对象
//进行过滤操作,在线化简时,这里就是执行局部搜索策略
doSomething();
} else if(method.getName().equals("addAll")) {
List<IChromosome> list = (List<IChromosome>) args[0];
for(int i=0; i<list.size(); i++) {
addedThing = (T)list.get(i); //被添加的对象
//进行过滤操作,在线化简时,这里就是执行局部搜索策略
doSomething ();
}
}
}

//拦截完毕,放行
Object result = methodProxy.invokeSuper(object, args);
return result;
}
}


2.2 主要的调用方法

针对上述代理,其调用方式如下:

import net.sf.cglib.proxy.Enhancer;
// 设置java.util.List的动态代理
Enhancer en = new Enhancer();
// 进行代理
en.setSuperclass(java.util.ArrayList.class);
en.setCallback(new ListAddMethodInterceptor(pts, distanceTolerance));
// en.setCallbackFilter(new ListCallbackFilter());
@SuppressWarnings("unchecked")
List<IChromosome> popu = (List<IChromosome>) en.create();
// 动态代理设置结束


3 cgLib与JDK相比的优势

cgLib与JDK相比最大的好处就是不再需要主题有抽象接口。例如HelloImpl类,如果它没有Hello接口则无法使用动态代理,而利用cgLib则没有这方面的限制。

全文完。转载请注明出处。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: