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

这篇文章主要介绍利用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则没有这方面的限制。


全文完。转载请注明出处。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值