手写代理框架
动态代理的原理
- 拿到被代理对象的引用,然后获取它的接口
- jdk代理重新生成一个类,同时实现我们给的代理所实现的接口
- 把被代理对象的引用也拿到
- 重新动态生成一个class字节码
- 然后编译
package com.customproxy;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.URL;
import java.net.URLClassLoader;
public class ProxyUtils {
public static Object newInstance(Object target){
Object proxy=null;
Class<?> tragetInf = target.getClass().getInterfaces()[0];
StringBuffer sb = new StringBuffer();
String line="\n";
String tab ="\t";
String interType = tragetInf.getSimpleName();
sb.append("package com.google;");
sb.append(line);
sb.append("import "+tragetInf.getName()+";");
sb.append(line);
String infName = tragetInf.getName();
sb.append("public class $Proxy implements "+infName+" {");
sb.append(line);
sb.append(tab+"private "+ interType+" target;");
sb.append(line);
sb.append(tab+tab+ "public $Proxy("+interType+" target){");
sb.append(line);
sb.append(tab+tab+"this.target=target;");
sb.append(line);
sb.append(tab+tab+"}");
sb.append(line);
Method[] methods = tragetInf.getDeclaredMethods();
for (Method m:methods ) {
Class<?> returnType = m.getReturnType();
String returnTypeSimpleName = returnType.getSimpleName();
String mothodName = m.getName();
Parameter[] parameters = m.getParameters();
StringBuffer praCon = new StringBuffer();
StringBuffer parV = new StringBuffer();
int p=0;
for (Parameter parameter: parameters){
String pType = parameter.getType().getSimpleName();
praCon.append(pType+" arg"+p+",");
parV.append(" arg"+p+",");
}
String aa="";
String bb="";
if(parameters.length>0){
aa = praCon.substring(0,praCon.lastIndexOf(",")-1);
bb = parV.substring(0,parV.lastIndexOf(",")-1);
}
sb.append(tab+tab+"public "+returnTypeSimpleName+" "+ mothodName +"("+aa+"){");
sb.append(line);
sb.append(tab+tab+"System.out.println(\"log\");"+line);
sb.append(line);
sb.append(tab+tab+"target."+mothodName+" ( "+bb+");");
sb.append(line);
sb.append(tab+"}");
sb.append(line);
sb.append("}");
File file =new File("d:\\com\\google\\$Proxy.java");
try {
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file);
fw.write(sb.toString());
fw.flush();
fw.close();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable units = fileMgr.getJavaFileObjects(file);
JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
t.call();
fileMgr.close();
URL[] urls = new URL[]{new URL("file:D:\\\\")};
URLClassLoader urlClassLoader = new URLClassLoader(urls);
Class clazz = urlClassLoader.loadClass("com.google.$Proxy");
Constructor constructor = clazz.getConstructor(tragetInf);
proxy = constructor.newInstance(target);
}catch (Exception e){
e.printStackTrace();
}
}
sb.append("}");
return proxy;
}
}
package com.customproxy;
public class Test {
public static void main(String[] args) {
UserDao userDao = (UserDao) ProxyUtils.newInstance(new UserDaoImpl());
userDao.saveUser("ddddd");
}
}
package com.customproxy;
public interface UserDao {
public void saveUser(String user);
}
package com.customproxy;
public class UserDaoImpl implements UserDao {
public void saveUser(String user) {
System.out.println("saveUser");
}
}
利用jdk 代理实现
package com.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
public Object realObject;
public ProxyHandler(Object obj){
this.realObject=obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("可以在调用实际方法前做一些事情");
System.out.println("当前调用的方法是" + method.getName());
result = method.invoke(realObject,args);
System.out.println(method.getName() + "方法的返回值是" + result);
System.out.println("可以在调用实际方法后做一些事情");
System.out.println("------------------------");
return result;
}
}
package com.jdkproxy;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
UserDao userDao = new UserDaoImpl();
ProxyHandler handler = new ProxyHandler(userDao);
UserDao userProxy = (UserDao) Proxy.newProxyInstance(
UserDao.class.getClassLoader(),
new Class[]{UserDao.class}, handler);
userProxy.saveUser("ddd");
}
}
package com.jdkproxy;
public interface UserDao {
public void saveUser(String user);
}
package com.jdkproxy;
public class UserDaoImpl implements UserDao {
public void saveUser(String user) {
System.out.println("saveUser");
}
}