简单实现jdk的动态代理
jdk动态代理的使用
package com.util;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Test {
//产生代理对象
public static <T>T getBean(final MyService oldService){
return (T)Proxy.newProxyInstance(oldService.getClass().getClassLoader(), oldService.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2)
throws Throwable {
System.out.println("原方法之前");
//定义一个对象保存原方法返回值
Object o = null ;
try {
o = arg1.invoke(oldService, arg2) ;
} catch (Exception e) {
System.out.println(e);
}
System.out.println("原方法之后");
return o;
}
}) ;
}
//被代理类
static class MyService implements MyServiceInter{
@Override
public void say() {
System.out.println("原方法");
}
}
//jdk的动态代理需要提供接口,还有一种动态代理是使用继承实现的可参考cglib的使用
interface MyServiceInter{
void say() ;
}
public static void main(String[] args) {
MyServiceInter service = getBean(new MyService()) ;
service.say();
}
}
运行结果:
原方法之前
原方法
原方法之后
可以发现方法已经被代理了
模仿jdk动态代理写一个自己的动态代理
首先需要一个接口:InvocationHandler,一个产生代理类的类:Proxy
InvocationHandler.java
package 动态代理实现;
import java.lang.reflect.Method;
public interface InvocationHandler {
Object invock(Object object , Method m , Object[] objs) ;
}
Proxy.java
package 动态代理实现;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class Proxy {
public static Object newProxyInstance(Class<?> intaface,InvocationHandler handler){
//保存生成代理类的字符串
StringBuffer buf = new StringBuffer() ;
//产生这个java类的代码
String className = "Proxy"+intaface.getSimpleName() ;
//添加包名
buf.append("package com.proxy.temp ; \r\n\r\n");
buf.append("import "+InvocationHandler.class.getName() + " ; \r\n\r\n") ;
//添加类的主体
buf.append("public class "+className+" implements "+intaface.getName() +" { \r\n\r\n") ;
//添加构造方法
buf.append("InvocationHandler handler ; \r\n\r\n") ;
buf.append("public "+className+"(InvocationHandler handler){ \r\n\r\n") ;
buf.append("this.handler = handler ; \r\n\r\n} \r\n\r\n") ;
//将代理方法全部实现
Method[] ms = intaface.getMethods() ;
for (Method m : ms) {
//保存方法参数
String parames = "" ;
String pnameStrings = "" ;
String ptype = "" ;
Parameter[] ps = m.getParameters() ;
for (int i=0 ; i<ps.length ; i++) {
parames += ps[i].getType().getName()+".class ," ;
pnameStrings += "arg"+i + " ," ;
ptype += ps[i].getType().getName()+" arg"+i +" ," ;
}
//写方法体
buf.append("@Override \r\n") ;
buf.append("public "+m.getReturnType().getName()+" "+m.getName()+"("+(ptype.equals("") ? "" : ptype.substring(0 , ptype.length()-1))+") {\r\n\r\n") ;
//保存方法的反射
buf.append(Method.class.getName()+" method = null ; \r\n\r\n") ;
buf.append("try{ \r\n\r\n") ;
buf.append("method = "+intaface.getName()+".class.getDeclaredMethod(\""+m.getName()+"\" " + (parames.equals("") ? "" : "," + parames.substring(0 , parames.length()-1))+") ; \r\n\r\n") ;
buf.append("}catch(Exception e){ \r\n\r\nSystem.out.println(e) ;\r\n\r\n}\r\n\r\n") ;
//返回数据
String returnStr = "" ;
if(!m.getReturnType().toString().equals("void")){
returnStr = "return ("+m.getReturnType().getName()+")" ;
}
buf.append(returnStr+"this.handler.invock(this , method , "+(pnameStrings.equals("") ? "null" : "new Object[]{"+ pnameStrings.subSequence(0, pnameStrings.length() - 1)+"}")+") ; \r\n\r\n") ;
buf.append("} \r\n\r\n") ;
}
buf.append("}") ;
writeToFile(className+".java", buf);
return compileToFileAndLoadclass("com.proxy.temp."+className , className+".java" , handler) ;
}
//编译代理类产生class文件
private static Object compileToFileAndLoadclass(String className,String fileStr,InvocationHandler handler){
//使用多进程编译代理类
Process p = null ;
BufferedReader reader = null ;
try {
//System.out.println("javac "+"javac -cp "+System.getProperty("user.dir")+"\\src\\ "+System.getProperty("user.dir")+"\\"+fileStr +" -d "+System.getProperty("user.dir")+"\\bin");
p = Runtime.getRuntime().exec("javac -cp "+System.getProperty("user.dir")+"\\src\\ "+System.getProperty("user.dir")+"\\"+fileStr +" -d "+System.getProperty("user.dir")+"\\bin") ;
reader = new BufferedReader(new InputStreamReader(p.getErrorStream())) ;
String line = "" ;
while((line = reader.readLine()) != null){
System.out.println(line);
}
Object o = getInstance(className , handler) ;
return o ;
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null ;
}
//利用反射产生一个代理类
private static Object getInstance(String className , InvocationHandler handler){
try {
Class c = Thread.currentThread().getContextClassLoader().loadClass(className) ;
Constructor con = c.getConstructor(InvocationHandler.class) ;
return con.newInstance(handler) ;
} catch (Exception e) {
return null ;
}
}
//将产生的代理类保存到磁盘
private static void writeToFile(String fileName , StringBuffer data){
FileWriter fw = null ;
try {
fw = new FileWriter(fileName) ;
fw.write(data.toString());
} catch (Exception e) {
System.out.println(e);
} finally{
if(fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
对自己封装的动态代理进行测试
准备:接口类,被代理类,测试代码
ServiceInter.java
package 测试;
public interface ServiceInter {
public abstract void say();
}
Server.java
package 测试;
public class Service implements ServiceInter {
public void say() {
System.out.println("laile");
}
}
Test.java
package 测试;
import java.lang.reflect.Method;
import 动态代理实现.InvocationHandler;
import 动态代理实现.Proxy;
public class Test {
public static void main(String[] args) {
final ServiceInter oldService = new Service() ;
ServiceInter service = (ServiceInter) Proxy.newProxyInstance(ServiceInter.class, new InvocationHandler() {
public Object invock(Object object, Method m, Object[] objs) {
System.out.println("before");
Object o = null ;
try {
o = m.invoke(oldService, objs) ;
} catch (Exception e) {
System.out.println(e);
}
System.out.println("after");
return o;
}
}) ;
service.say();
}
}
程序运行结果
before
laile
after
可以看出动态代理功能已经实现了(其实动态代理和静态代理差不多,只是代理类如果使用静态代理要几个就得写几个,但如果是动态代理的话代理类就是动态生成的)