Dynamic Proxy&Spring AOP

jdk中动态代理的实现


Client

package com.dp.proxy;

import java.io.Serializable;

/**
 * 动态代理
 * */
public class Client {

	public static void main(String[] args) {
 
		Moveable t = new Tank();
		InvocationHandler h = new TimeHandler(t);  //对t的时间代理操作
		Moveable m = (Moveable)new Proxy().newProxyInstance(Moveable.class,h);
		m.move();
	}
}
/*
D:\eclipse-workspace\Proxy-jdk
com.sun.tools.javac.api.JavacTool
class com.dp.proxy.TankTimeProxy
Tank moving
time:751
 */

Moveable

package com.dp.proxy;

public interface Moveable {
	void move();
}

Tank

package com.dp.proxy;

import java.util.Random;

public class Tank implements Moveable{

	public void move() {
		System.out.println("Tank moving");
		try { //此线程休眠1000毫秒以内随机数
			Thread.sleep(new Random().nextInt(1000));
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

InvocationHandler

package com.dp.proxy;

import java.lang.reflect.Method;
/**
 * 对任意方法进行自定义处理
 * 具体处理放在实现类中
 * */
public interface InvocationHandler {
	public void invoke(Object o,Method m);
}

TimerHandler

package com.dp.proxy;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * 对被代理的类加一些时间的逻辑处理
 * */
public class TimeHandler implements InvocationHandler {

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


	@Override
	public void invoke(Object o,Method m) {
		long start = System.currentTimeMillis();  //加入代理逻辑
		try {
			m.invoke(target);  //简单起见假设参数为空   调用方法target.m()
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		long end = System.currentTimeMillis();
		System.out.println("time:"+(end-start));	
	}

}

Proxy

package com.dp.proxy;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;

/**
 * JDK Compiler API,
 * CGLib,ASM 直接生成二进制文件
 * 根据被代理的类实现的接口和要进行的具体的代理操作的类动态实现代理
 * 可以对任意的对象、任意的接口方法,实现任意的代理
 * */
public class Proxy {
	public static Object newProxyInstance(Class intfce,InvocationHandler h) {
		String rt = "\r\n";  //回车和换行
		String methodStr = "";
		Method[] methods = intfce.getMethods();
		
		for(Method m:methods) {
			methodStr +=
					"    @Override"+rt+
					"    public void "+m.getName()+"() {"+ rt +    //简单起见假设这里方法都为void
					"    Method method = null;"+rt+
					"    try {"+rt+
					"        method = "+intfce.getName()+".class.getMethod(\""+m.getName()+"\");"+rt+
					"    } catch (NoSuchMethodException | SecurityException e) {" + rt + 
					"		e.printStackTrace();" +rt + 
					"    }"+rt+
					"    h.invoke(this,method);"+ rt +	
					"    }"+ rt ;
		}
		
		String src = 
		"package com.dp.proxy;"+ rt +
		"import java.lang.reflect.Method;"+rt+
		"public class $proxy1 implements "+intfce.getName()+"{"+ rt +

		"    InvocationHandler h;"+rt+
		"    public $proxy1(InvocationHandler h) {"+ rt +
		"		 super();"+ rt +
		"		 this.h = h;"+ rt +
		"	}"+ rt +
			methodStr+
		"}";

		String fileName = System.getProperty("user.dir");
		System.out.println(fileName);//项目根路径  D:\eclipse-workspace\Proxy-jdk
		fileName = fileName+"/src/com/dp/proxy/$proxy1.java";
		File f = new File(fileName);
		try {
			FileWriter fw = new FileWriter(f);
			fw.write(src);
			fw.flush();
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//compile     javac 
		//得到编译器对象
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
		//编译文件时,会找到JAVA_HOME的jre\lib\tools.jar,但tools.jar并不在jre中,它是在jdk\lib
		//值为null的解决办法:将jdk\lib下将tools.jar复制到jre\lib下
		System.out.println(compiler.getClass().getName());//com.sun.tools.javac.api.JavacTool
		StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
		Iterable utils = fileMgr.getJavaFileObjects(fileName);
		CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, utils);
		t.call();
		try {
			fileMgr.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//生成了.class文件
		
		//load into memory and create an instance
		URL[] urls = null;
		try {
			urls = new URL[] {new URL("file:/"+System.getProperty("user.dir")+"/src/")};
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		URLClassLoader ul = new URLClassLoader(urls);
		try {
			Class c = ul.loadClass("com.dp.proxy.$proxy1");
			System.out.println(c);   //class com.dp.proxy.TankTimeProxy
			//拿到重载的构造方法
			Constructor ctr = c.getConstructor(InvocationHandler.class);  
     		Object o = (Object)ctr.newInstance(h);
			
 			return o;
		} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalArgumentException 
				| InstantiationException | IllegalAccessException | InvocationTargetException e) {
			e.printStackTrace();
		}
		
		return null;
	}
}

生成的代理类$proxy1

package com.dp.proxy;
import java.lang.reflect.Method;
public class $proxy1 implements com.dp.proxy.Moveable{
    InvocationHandler h;
    public $proxy1(InvocationHandler h) {
		 super();
		 this.h = h;
	}
    @Override
    public void move() {
    Method method = null;
    try {
        method = com.dp.proxy.Moveable.class.getMethod("move");
    } catch (NoSuchMethodException | SecurityException e) {
		e.printStackTrace();
    }
    h.invoke(this,method);
    }
}

test包

Client

package com.dp.proxy.test;

import com.dp.proxy.InvocationHandler;
import com.dp.proxy.Proxy;

public class Client {

	public static void main(String[] args) {
		UserMgr u = new UserMgrImpl();
		InvocationHandler h = new TransactionHandler(u);
		UserMgr um = (UserMgr)Proxy.newProxyInstance(UserMgr.class, h);
		um.addUser();
	}

}
/*
D:\eclipse-workspace\Proxy-jdk
com.sun.tools.javac.api.JavacTool
class com.dp.proxy.$proxy1
Transaction start
1.插入记录到User表
2.做日志到另外一张表
Transaction commit
 */

UserMgr

package com.dp.proxy.test;

public interface UserMgr {
    void addUser();
}

UserMgrImpl

package com.dp.proxy.test;

public class UserMgrImpl implements UserMgr{

	@Override
	public void addUser() {
		System.out.println("1.插入记录到User表");
		System.out.println("2.做日志到另外一张表");
	}

}

TranscationHandler

package com.dp.proxy.test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.dp.proxy.InvocationHandler;

public class TransactionHandler implements InvocationHandler{
	
	private Object target;
	public TransactionHandler(Object o) {
		super();
		this.target = o;
	}
	@Override
	public void invoke(Object o, Method m) {
		System.out.println("Transaction start");
		try {
			m.invoke(target);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		System.out.println("Transaction commit");
	}
	
}

生成的代理类$proxy1

package com.dp.proxy;
import java.lang.reflect.Method;
public class $proxy1 implements com.dp.proxy.test.UserMgr{
    InvocationHandler h;
    public $proxy1(InvocationHandler h) {
		 super();
		 this.h = h;
	}
    @Override
    public void addUser() {
    Method method = null;
    try {
        method = com.dp.proxy.test.UserMgr.class.getMethod("addUser");
    } catch (NoSuchMethodException | SecurityException e) {
		e.printStackTrace();
    }
    h.invoke(this,method);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值