`

JDK代理的应用及优化示例

    博客分类:
  • JDK
阅读更多
1. 首先定义一个接口.
package proxy;
/** 
 *  操作接口
 *  version 1.0 Jul 15, 2010
 */
public interface ITarget {
	
	/**
	 *  操作方法
	 */
	public void operator();
	
}

2. 再定义一个接口的实现类
package proxy.impl;

import proxy.ITarget;

public class Target implements ITarget { 

	@Override
	public void operator() {
		// TODO Auto-generated method stub
		System.out.println(">>>正在调用Targer.operator()方法!"); 
	}

}

我们使用面向接口编程,最简单的调用方式是[1]
		ITarget it=new Target();
		it.operator();

然而使用这种调用方式使得接口和实现通过硬编码的方式耦合在了一起.
JDK动态代理可以生成一个代理对象.
3.  创建JDK动态代理Handler[2]
package proxy.handler;

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

public class MethodHandler implements InvocationHandler {

	private Object targetObject;

	public Object newProxy(Object targetObject) {
		this.targetObject = targetObject;
		return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
				targetObject.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		Object ret = null;
		try {
			ret = method.invoke(this.targetObject, args);
		} catch (Exception e) {
			e.printStackTrace();
			throw new java.lang.RuntimeException(e);
		}
		return ret;
	}
}


4. 创建调用接口.
                  MethodHandler handler=new MethodHandler();
		ITarget ii=(ITarget)handler.newProxy(new Target());
		ii.operator();


看到这里我发现了,当我们调用Spring中的getBean(),他会返回一个初始化好的实例给你.
IOC很简单的把程序的耦合[1],移到了配置文件ApplicationContext.xml当中;当我们调用Spring中的AOP时,他会返回一个初始化好的实例给你,但是这个实例是一个JKDProxy,这样就可以在invoke中添加一些自定义的行为[2].
总结:约定优于配置,我们完全可以跳过JDK的动态代理来实现完全基于IOC的“伪”动态代理,规则如下:
存储路径规则:
proxy:存储接口
proxy.impl:存储接口的实现类
类名定义规则:
ITarget:接口类名
Target:接口实现类名
注意:接口的类名必须以"I"开头,后面符合Java命名规范,实现类必须为接口名称去掉"I".
5. "伪"动态代理
package proxy.handler;

public class ChgHandler {
	
	public Object invoke(Class interfaceName) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
		String path=interfaceName.getName();
		int point=path.lastIndexOf(".");
		String pack=path.substring(0,point);
		String clsname=path.substring(point+1);
		String proxyimpl=pack.concat(".impl");
		String proxynameimpl=clsname.replaceFirst("I", "");
		String proxyName=proxyimpl.concat(".").concat(proxynameimpl);
		Class<?>  proxyclass=Class.forName(proxyName);
		return proxyclass.newInstance();
	}

}


6. 对伪代理的调用
ChgHandler chgh=new ChgHandler();
		ITarget hh=(ITarget) chgh.invoke(ITarget.class);
		hh.operator();

这样可以替代JDK动态代理,而且其实现效率更高,不需要Spring配置,只需要通过这个"伪"代理就可以实现从接口到实现的转换,其出错的概率也更低.
当然我这里给出的只是一个简单的范例,代码也是草草,不能和Spring这强大的框架相比,但是其效率绝对是最高的.
这里还有很多需要完善的,比如说代理对象有复杂的对象作为其输入参数,还有日志及其异常处理等等.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics