静态代理
package proxy.statical;
import proxy.Coder;
import proxy.Person;
public class RobotProxy implements Person {
private Coder coder;
public RobotProxy(Coder coder) {
this.coder = coder;
}
@Override
public void cleaning() {
System.out.println("robot cleaning 准备");
coder.cleaning();
System.out.println("robot cleaning 完毕");
}
@Override
public void cooking() {
System.out.println("robot cooking 准备");
coder.cooking();
System.out.println("robot cooking 完毕");
}
}
测试
package proxy.statical;
import proxy.Coder;
public class StaticalTest {
public static void main(String[] args) {
RobotProxy robotProxy = new RobotProxy(new Coder());
robotProxy.cleaning();
robotProxy.cooking();
}
}
动态代理
jdk
package proxy.dynamic.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler {
private Object target;
public Object getJDKProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("jdk动态代理,开始");
Object invoke = method.invoke(target, args);
System.out.println("jdk动态代理,结束");
return invoke;
}
}
package proxy.dynamic.jdk;
import proxy.Coder;
import proxy.Person;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
import java.io.IOException;
public class JdkProxyTest {
public static void main(String[] args) {
JDKProxy jdkProxy = new JDKProxy();
Person person = (Person) jdkProxy.getJDKProxy(new Coder());
person.cleaning();
person.cooking();
viewSourceCode();
}
/**
* 查看动态代理动态生成的代码
*/
public static void viewSourceCode() {
byte[] proxyClass = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class});
try {
FileOutputStream fos = new FileOutputStream("E://$Proxy.class");
fos.write(proxyClass);
} catch (IOException e) {
e.printStackTrace();
}
}
}
cglib
需要导入俩包
- asm-7.2.jar
- cglib-3.3.0.jar
package proxy.dynamic.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor {
private Object target;
public Object getCglibProxy(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
//设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类
enhancer.setSuperclass(target.getClass());
// 设置回调
enhancer.setCallback(this);
//创建并返回代理对象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib动态代理,开始");
Object invoke = method.invoke(target, objects);
System.out.println("cglib动态代理,结束");
return invoke;
}
}
测试
package proxy.dynamic.cglib;
import proxy.Coder;
import proxy.Person;
public class CglibProxyTest {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
Person person = (Person) cglibProxy.getCglibProxy(new Coder());
person.cleaning();
person.cleaning();
}
}
手写实现jdk动态代理
package proxy.custom;
import proxy.custom.source.MyClassLoader;
import proxy.custom.source.MyInvocationHandler;
import proxy.custom.source.MyProxy;
import java.lang.reflect.Method;
public class CustomProxy implements MyInvocationHandler {
private Object target;
public Object getCustomProxy(Object target) {
this.target = target;
return MyProxy.newProxyInstance(new MyClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
System.out.println("jdk动态代理,开始");
Object invoke = method.invoke(target, args);
System.out.println("jdk动态代理,结束");
return invoke;
}
}
package proxy.custom.source;
import java.lang.reflect.Method;
public interface MyInvocationHandler {
Object invoke(Object invoke, Method method, Object[] args) throws Exception;
}
package proxy.custom.source;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class MyClassLoader extends ClassLoader {
private File classPathFile;
public MyClassLoader() {
String classPath = MyClassLoader.class.getResource("").getPath();
this.classPathFile = new File(classPath);
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
// String className = MyClassLoader.class.getPackage().getName() + "." + name;
// proxy/custom/source/$Proxy0 (wrong name: proxy/custom/$Proxy0)
// 这里有个问题,class文件生成在proxy/custom/source/下,写该路径却有上面的异常。
String className = "proxy/custom/$Proxy0";
if (classPathFile != null) {
File classfile = new File(classPathFile, name.replaceAll("\\.", "/") + ".class");
if (classfile.exists()) {
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(classfile);
out = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len;
while ((len = in.read(buff)) != -1) {
out.write(buff, 0, len);
}
return defineClass(className, out.toByteArray(), 0, out.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
}
package proxy.custom.source;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
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;
public class MyProxy {
public static final String LN = "\r\n";
/**
* 原理,字节码重组
* 1、拿到被代理对象的引用,并且获取到它的所有的接口,反射获取
* 2、JDK Proxy类重新生成一个新的类,同时新的类要实现被代理类所有实现的所有的接口
* 3、动态生成Java代码,把新加的业务逻辑方法由一定的逻辑代码去调用(在代码中体现)
* 4、编译新生成的Java代码.class
* 5、再重新加载到JVM中运行
* 以上这个过程就叫字节码重组
* JDK中有个规范,只要欧式$开头的一般都是自动生成的
*/
public static Object newProxyInstance(MyClassLoader classLoader, Class<?>[] interfaces, MyInvocationHandler h) {
try {
// 1、动态生成源代码.java文件
String src = generateSrc(interfaces);
// 2、Java文件输出存盘
String path = MyProxy.class.getResource("").getPath();
File f = new File(path + "$Proxy0.java");
FileWriter fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
// 3、把生成的.java文件编译成.class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> iterable = manager.getJavaFileObjects(f);
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
task.call();
manager.close();
// 4、编译生成的.class文件加载到JVM中
Class<?> proxyClass = classLoader.findClass("$Proxy0");
Constructor<?> constructor = proxyClass.getConstructor(MyInvocationHandler.class);
f.delete();
// 5、返回字节码重组以后的新的代理对象
return constructor.newInstance(h);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String generateSrc(Class<?>[] interfaces) {
StringBuffer sb = new StringBuffer();
sb.append("package proxy.custom;" + LN);
sb.append("import proxy.Person;" + LN);
sb.append("import proxy.custom.source.MyInvocationHandler;" + LN);
sb.append("import java.lang.reflect.Method;" + LN);
sb.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + LN);
sb.append("MyInvocationHandler h;" + LN);
sb.append("public $Proxy0(MyInvocationHandler h) { " + LN);
sb.append("this.h = h;");
sb.append("}" + LN);
for (Method m : interfaces[0].getMethods()) {
sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + LN);
sb.append("try {" + LN);
sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\", new Class[]{});" + LN);
sb.append("this.h.invoke(this, m, null);" + LN);
sb.append("} catch (Throwable e) {" + LN);
sb.append("e.printStackTrace();" + LN);
sb.append("}" + LN);
sb.append("}" + LN);
}
sb.append("}" + LN);
return sb.toString();
}
}
测试
package proxy.custom;
import proxy.Coder;
import proxy.Person;
import proxy.custom.source.MyClassLoader;
public class CustomProxyTest {
public static void main(String[] args) throws ClassNotFoundException {
CustomProxy customProxy = new CustomProxy();
Person person = (Person) customProxy.getCustomProxy(new Coder());
person.cleaning();
person.cooking();
// test();
}
public static void test() throws ClassNotFoundException {
MyClassLoader myClassLoader = new MyClassLoader();
// System.out.println(myClassLoader.findClass("MyProxy"));
System.out.println(myClassLoader.findClass("$Proxy0"));
}
}
公用接口和类
package proxy;
public interface Person {
void cleaning();
void cooking();
}
package proxy;
public class Coder implements Person {
@Override
public void cleaning() {
System.out.println("cleaning");
}
@Override
public void cooking() {
System.out.println("cooking");
}
}