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

时间:2022-02-10 05:10:11


动态代理中有两个类: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();
}


}


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

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();
}
}
}


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

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

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