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

自己编写动态代理机制代码,深入了解动态代理

2017-06-12 20:01 639 查看
动态代理中有两个类:Proxy类:生成代理类

InvocationHandler接口:处理事务的

Proxy类通过,传入的接口的类类型创建一个代理类实现动态,那么它是如何创建的呢?

创建的步骤如下:

1.编写源码(代理类,实现继承接口)

2.编译源码

3.加载进内存,生成代理对象

4.返回代理对象

代码如下:

package com.imooc.proxy;

import java.io.File;

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

import javax.tools.JavaCompiler;

import javax.tools.JavaCompiler.CompilationTask;

import javax.tools.StandardJavaFileManager;

import javax.tools.ToolProvider;

import org.apache.commons.io.FileUtils;

public class Proxy {

public static Object newProxyInstance(Class inface,InvocationHandler h) throws Exception{

String rt = "\r\n";
String methodstr = "";

//通过接口生成代理对象的方法
for(Method m:inface.getMethods()){
methodstr += 
" @Override"+rt+
" public void "+m.getName()+"() {"+rt+
" // TODO Auto-generated method stub"+rt+
"       try{"+rt+
" Method md = "+inface.getName()+".class.getMethod(\""+m.getName()+"\");"+rt+
" h.invoke(this,md,null);"+rt+
" }catch(Exception e){e.printStackTrace();}"+rt+

" }"+rt;
}

//代理类
String proxyClass = 
"package com.imooc.proxy;"+rt+
"import java.lang.reflect.Method;"+rt+
"public class $Proxy0 implements " + inface.getName()+ " {"+rt+
" private "+inface.getName()+" m;"+rt+
"   private InvocationHandler h;"+rt+
" public $Proxy0( InvocationHandler h){"+rt+
" this.h = h;"+rt+
" }"+rt+
methodstr+rt+
" }"+rt;

//编写源代码
String filename = System.getProperty("user.dir")+"/bin/com/imooc/proxy/$Proxy0.java";
File file = new File(filename);
FileUtils.write(file, proxyClass);
System.out.println(filename);

//编译
//获得编译器
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//文件管理者
StandardJavaFileManager filemgr = compiler.getStandardFileManager(null, null, null);
//获取文件
Iterable units = filemgr.getJavaFileObjects(filename);
//获取编译任务
CompilationTask c = compiler.getTask(null, filemgr, null, null, null, units);
//编译
c.call();
filemgr.close();

//加载类
//获得加载器
ClassLoader cl = ClassLoader.getSystemClassLoader();
//加载
Class<?>  cla = cl.loadClass("com.imooc.proxy.$Proxy0");
System.out.println(cla.getName());
//生成对象
//通过构造方法生成对象
Constructor cst = cla.getConstructor(InvocationHandler.class);
return cst.newInstance(h);
}

}

InvocationHandler:管理事务的,可以添加日志,花费时间等等事务

先声明一个接口类:

package com.imooc.proxy;

import java.lang.reflect.Method;

public interface InvocationHandler {

public Object invoke(Object obj,Method method,Object[] args);

}

然后实现具体事务,继承接口:

我这里是实现花费时间

package com.imooc.proxy;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

public class TimeHandler implements InvocationHandler {

private Object target;

public TimeHandler(Object target){
this.target = target;
}

@Override
public Object invoke(Object obj, Method method, Object[] args) {
// TODO Auto-generated method stub
try {
//添加事务--->时间
long start = System.currentTimeMillis();
//调用目标类的方法
method.invoke(target, args);
long end = System.currentTimeMillis();
System.out.println("生产的时间为:"+(end-start)+"毫秒");

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

}

测试:

package com.imooc.proxy;

public class Test {

public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
LiningClothing lc = new LiningClothing();
InvocationHandler h = new TimeHandler(lc);
ClothingFactory lf = (ClothingFactory)Proxy.newProxyInstance(ClothingFactory.class,h);
lf.productClothing();
}

}

c883

还有需要用的接口(被代理类的接口)和目标类(被代理的类)

package com.imooc.proxy;

public interface ClothingFactory {

public void productClothing();

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

package com.imooc.proxy;

public class LiningClothing implements ClothingFactory {

@Override
public void productClothing() {
// TODO Auto-generated method stub
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

===========================================================

当生成的代理对象调用方法的流程:

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