1、简单的demo
public interface HelloService {
/**
* 目标方法
*/
public abstract void add(String str);
}
public class HelloServiceImpl implements HelloService {
/*
* @see dynamic.proxy.UserService#add()
*/
public void add(String str) {
System.out.println("==>"+str);
}
}
//代理类
public class HelloServiceProxy implements InvocationHandler {
// 目标对象
private Object target;
/**
* 执行目标对象的方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在目标对象的方法执行之前简单的打印一下
System.out.println("------------------before------------------");
// 执行目标对象的方法
Object result = method.invoke(target, args);
// 在目标对象的方法执行之后简单的打印一下
System.out.println("-------------------after------------------");
return result;
}
/**
* 获取目标对象的代理对象
* @param target 目标对象
* @return 代理对象
*/
public Object getProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(), this);
}
}
测试代码
public class Test{
public static void main(String[] args) {
HelloService service = new HelloServiceImpl();
HelloServiceProxy proxy = new HelloServiceProxy();
//绑定代理对象。
service = (HelloService) proxy.getProxy(service);
//这里service经过绑定,就会进入invoke方法里面了。
service.add("hello");
}
}
执行结果:
——————before——————
==>hello
——————-after——————
2、代码分析
//Proxy.java
//通过反射 获取代理类HelloServiceImpl的实例
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
//克隆一份被代理目标类所实现所有接口的 Class对象数组
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
//拿到代理类的Class 主要的方法
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//拿到代理类的Constructor对象,以便用于构造代理对象
final Constructor<?> cons = cl.getConstructor(constructorParams);
//h为InvocationHandler的实现类HelloServiceProxy
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
////返回构造的代理类对象,这里留个意,传入的是 实现了InvocationHandler接口的对象
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
主要是跟getProxyClass0的代码,
//主要通过这两个方法获取HelloServiceImpl的Class对象
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
详见:http://blog.youkuaiyun.com/scplove/article/details/52451899
3、实际的调用过程
通过ProxyGeneratorUtils生成HelloServiceImpl的class文件并保持在磁盘上
public class ProxyGeneratorUtils {
/**
* 把代理类的字节码写到硬盘上
*/
public static void writeProxyClassToHardDisk(String path) {
// 获取代理类的字节码 方法的第二个参数为被代理类所实现的全部接口
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", HelloServiceImpl.class.getInterfaces() );
FileOutputStream out = null;
try {
out = new FileOutputStream( path );
out.write( classFile );
out.flush();
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
}
用idea可以查看HelloServiceImpl生成的class文件
public final class $Proxy11 extends Proxy implements HelloService {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy11(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void add(String var1) throws {
try {
//h为HelloServiceProxy的实例 直接调用HelloServiceProxy的invoke方法。
//在HelloServiceProxy的invoke中,通过反射调用HelloServiceImpl的add方法
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final int hashCode() throws {
try {
return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
//通过反射获取add的Method实例
m3 = Class.forName("com.company.HelloService").getMethod("add", new Class[]{Class.forName("java.lang.String")});
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
总结:
主要步骤为
1、通过ProxyGenerator.generateProxyClass 获取HelloServiceImpl的class对象并使用反射实例化,还会获得add的Method对象
2、调用HelloServiceImpl通过反射得到的实例的add方法,在add方法中会调用HelloServiceProxy的invoke方法。最终通过反射调用HelloServiceImpl的add方法