动态代理
动态代理是相对静态代理(https://blog.csdn.net/weixin_43060721/article/details/82313877)而言,java动态代理是基于自动生成class文件字节码,然后将字节码动态(运行期而非编译器)加载到classloader,然后调用接口其实是调用字节码的代理类的对象的方法;相比于静态代理而言,不需要提前将类进行配置好,并且可以服务多个接口,比如写一个代理类,既可以代理A接口(让字节码类实现A接口的所有方法)也可以代理B接口((让字节码类实现B接口的所有方法),那就可以面向接口编程(AOP),而静态代理做不到这一点,java中使用动态代理如下:
接口和实际类:
public interface Subject {
public void print();
}
public class RealSubject implements Subject {
@Override
public void print() {
System.out.println("realSubject method!");
}
}
动态代理调用接口:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class SubjectInvocationHandler implements InvocationHandler {
private Subject subject;
public SubjectInvocationHandler(Subject subject) {
super();
this.subject = subject;
}
/**
* proxy:代表java自动生成$Proxy0.class的实例
* method:接口定义的方法
* args:方法的入参,可以为null
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
System.out.println("method invoke()");
Object result = method.invoke(subject, args);
System.out.println("after");
return result;
}
}
客户端:
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
//打开java生成代理类的开关
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
RealSubject realSubject = new RealSubject();
Subject subject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[] { Subject.class }, new SubjectInvocationHandler(realSubject));
subject.print();
}
}
结果:
before
method invoke()
realSubject method!
after
java自动生成类的位置:
自动生成类的字节码:
/*** Eclipse Class Decompiler plugin, copyright (c) 2016 Chen Chao (cnfree2000@hotmail.com) ***/
package com.sun.proxy;
import Subject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Subject {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void print()
throws
{//此处调用print()方法
try
{
this.h.invoke(this, m3, null);//这里会将自己传给invokeHandler
return;
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return ((String)this.h.invoke(this, m2, null));
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("Subject").getMethod("print", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
} catch (NoSuchMethodException localNoSuchMethodException) {
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
} catch (ClassNotFoundException localClassNotFoundException) {
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}