简单实现jdk的动态代理

简单实现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

可以看出动态代理功能已经实现了(其实动态代理和静态代理差不多,只是代理类如果使用静态代理要几个就得写几个,但如果是动态代理的话代理类就是动态生成的)

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值