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

JAVA 设计模式 之 动态代理

2017-05-06 09:50 597 查看

JAVA的设计模式-JDK动态代理:实现控制 被代理类的方法执行前,执行后来做你想做的事。

1.自写代理模式示例代码

接口
public interface Subject{

public void doSomeThing();

}
实现类
public class RealObject implements Subject{

@Override
public void doSomeThing() {
System.out.println("doSomeThing..");
}

}
自写代理类
public class SimpleProxy {
Object obj = null;
public SimpleProxy(Object obj){
this.obj = obj;
}
public void doSomeThing(){
System.out.println("SimpleProxy doSomeThing start...");
this.obj.doSomeThing();
System.out.println("SimpleProxy doSomeThing end...");
}
}
执行
public class TestProxy {

public static void main(String[] args) {
Subject obj = new RealObject();
SimpleProxy simplePro = new SimpleProxy(obj);
simplePro.doSomeThing();
}
}
控制台打印结果
SimpleProxy doSomeThing start...
doSomeThing..
SimpleProxy doSomeThing end...

** 2:实现 InvocationHandler 接口 (充当SimpleProxy )来实现代理模式 示例代码**

接口
public interface Subject {

public void doSomeThing();

}
实现类
public class RealObject implements Subject{

@Override
public void doSomeThing() {
System.out.println("doSomeThing..");
}

}
代理类
public class DynamicProxy implements InvocationHandler {

Object obj = null;
public DynamicProxy(Object obj){
this.obj = obj;
}
@Override
public java.lang.Object invoke(java.lang.Object proxy, Method method,
java.lang.Object[] args) throws Throwable {
System.out.println("proxy class:"+proxy.getClass());
System.out.println("proxy name:"+proxy.getClass().getSimpleName());
System.out.println("method:"+method.getName());
return method.invoke(this.obj, args);
}

}
测试
public class TestProxy {

public static void main(String[] args) {

Subject sub = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class}, new DynamicProxy(new RealObject()));
sub.doSomeThing();
}
}

控制台输出:
proxy class:class com.sun.proxy.$Proxy0
proxy name:$Proxy0
method:doSomeThing
doSomeThing..

The last 分析源代码,实现接口InvocationHandler 具体做了什么。

昨天没有找到源码,,,,表示心也很累,,,, 进入Proxy.newProxyInstance() 方法

public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}

final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}

/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);

/*
* Invoke its constructor with the designated invocation handler.
*/
try {
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return newInstance(cons, ih);
}
});
} else {
return newInstance(cons, ih);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}

主要的是getProxyClass0()方法的调用,一直跟进,直接到代理工厂类ProxyClassFactory的apply() 其中多的是一些判断,无意看到了一个 IdentityHashMap集合。。呵呵 接着往下走,有一个 ProxyGenerator.generateProxyClass(proxyName, interfaces) proxyName是生产的代理对象类,interfaces是被代理的接口,并返回一个byte[]字节数组

public static byte[] generateProxyClass(String paramString, Class[] paramArrayOfClass)
{
ProxyGenerator localProxyGenerator = new ProxyGenerator(paramString, paramArrayOfClass);
final byte[] arrayOfByte = localProxyGenerator.generateClassFile();
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction()
{
public Void run()
{
try
{
FileOutputStream localFileOutputStream = new FileOutputStream(ProxyGenerator.dotToSlash(this.val$name) + ".class");

localFileOutputStream.write(arrayOfByte);
localFileOutputStream.close();
return null;
}
catch (IOException localIOException)
{
throw new InternalError("I/O exception saving generated file: " + localIOException);
}
}
});
}
return arrayOfByte;
}

返回的字节数组是实现了接口interfaces,类名称为proxyName的类, JDK根据既定规则直接生成class文件,用native方法加载了这个类,最终产生了一个实现了一个接口的类

private static native Class defineClass0(ClassLoader loader, String name,
byte[] b, int off, int len);

_传入的 new DynamicProxy(new RealObject()) _ 回到Proxy.newProxyInstance 的最后一行

return cons.newInstance(new Object[] {h} );

new DynamicProxy(new RealObject()) 可以理解是为生成的proxyName类转入的一个参数。

。。。。。在写这个的时候了解到CGLIB 也可以实现动态代理。只是产生动态代理对象时不用接口类! 写在离职前的几天。

(adsbygoogle = window.adsbygoogle || []).push({});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java EE Java Spring