Java 代理之JDK动态代理
用到的两个类, java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy
示例
UserService.java
package cn.cecurio.proxy.dynamic.jdk;
/**
* @author: Cecurio
* @create: 2018-02-25 16:20
**/
public interface UserService {
void add();
void update();
}
UserServiceImpl.java 委托类
package cn.cecurio.proxy.dynamic.jdk;
/**
* @author: Cecurio
* @create: 2018-02-25 16:22
**/
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("UserServiceImpl.add()");
}
public void update() {
System.out.println("UserServiceImpl.update()");
}
}
ServiceInvocationHandler.java
package cn.cecurio.proxy.dynamic.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author: Cecurio
* @create: 2018-02-25 16:24
**/
public class ServiceInvocationHandler implements InvocationHandler {
private Object target;
public ServiceInvocationHandler(Object target) {
this.target = target;
}
/**
* 创建代理实例
*
* @return
* @throws Throwable
*/
public Object getProxy() throws Throwable {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(),
this);
}
/**
* 实现 InvocationHandler 接口, 必须实现invoke方法
* 执行目标对象的方法, 并进行增强
*
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("代理方法开始");
System.out.println("被代理的方法是:" + method);
// 执行目标对象的方法
result = method.invoke(target, args);
System.out.println("代理方法结束");
return result;
}
}
JdkProxyTest.java 测试类
package cn.cecurio.proxy.dynamic.jdk;
/**
* @author: Cecurio
* @create: 2018-02-25 16:42
**/
public class JdkProxyTest {
public static void main(String[] args) throws Throwable {
UserService userService = new UserServiceImpl();
ServiceInvocationHandler handler = new ServiceInvocationHandler(userService);
UserService userServiceProxy = (UserService) handler.getProxy();
userServiceProxy.add();
}
}
执行结果
代理方法开始
被代理的方法是:public abstract void cn.cecurio.proxy.dynamic.jdk.UserService.add()
UserServiceImpl.add()
代理方法结束
JDK动态代理的用法:
- 一个接口
- 一个接口的实现类, 用作委托类
- 一个实现
java.lang.reflect.InvocationHandler
的类, 这个类有个成员变量(上面的接口实现类), 此类必须实现invoke(Object proxy, Method method, Object[] args)
方法 - 必须要有创建代理类的操作, 是上述代码的
UserService userServiceProxy = (UserService) handler.getProxy();
的部分, 生成的代理类继承Proxy, 实现委托类实现的接口
代理类的字节码是从哪里生成的?
进入java.lang.reflect.Proxy.ProxyClassFactory#apply()
方法,最终是通过调用sun.misc.ProxyGenerator#generateProxyClass(final String proxyName, Class<?>[] interfaces, int accessFlags)
方法生成byte[],然后调用方法java.lang.reflect.Proxy#defineClass0
,由类加载器加载生成对应的Class对象
到底生成了怎样的字节码? 我们可以自己调用sun.misc.ProxyGenerator#generateProxyClass(final String proxyName, Class<?>[] interfaces, int accessFlags)
这个方法去生成代理类的字节码,然后反编译看看
package cn.cecurio.proxy;
import sun.misc.ProxyGenerator;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
interface Service {
void add(String username,String password);
void update(String username,String password);
}
/**
* @author: Cecurio
* @create: 2018-04-07 2:11
**/
public class ProxyGeneratorTest {
public static void main(String[] args) {
String name = "ProxyService";
byte[] data = ProxyGenerator.generateProxyClass(name, new Class[]{Service.class});
FileOutputStream out = null;
try {
out = new FileOutputStream(name + ".class");
out.write(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != out) try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
动态生成的Service的实现类反编译后内容如下
import cn.cecurio.proxy.Service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class ProxyService
extends Proxy
implements Service
{
private static Method m1;
private static Method m3;
private static Method m4;
private static Method m2;
private static Method m0;
public ProxyService(InvocationHandler paramInvocationHandler)
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void add(String paramString1, String paramString2)
{
try
{
this.h.invoke(this, m3, new Object[] { paramString1, paramString2 });
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void update(String paramString1, String paramString2)
{
try
{
this.h.invoke(this, m4, new Object[] { paramString1, paramString2 });
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
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("cn.cecurio.proxy.Service").getMethod("add", new Class[] { Class.forName("java.lang.String"), Class.forName("java.lang.String") });
m4 = Class.forName("cn.cecurio.proxy.Service").getMethod("update", new Class[] { Class.forName("java.lang.String"), Class.forName("java.lang.String") });
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());
}
}
}
看到生成的构造函数需要一个InvocationHandler的实例,这个实例是怎么传递给ProxyService的构造函数的呢?是通过java.lang.reflect.Proxy#newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
这个方法,具体代码如下:
// cl是代理生成的Class对象
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 通过反射生成代理类的实例
return cons.newInstance(new Object[]{h});
Service接口的每个方法实现里都有类似下面的代码
this.h.invoke(this, m4, new Object[] { paramString1, paramString2 });
总结
JDK动态代理只做了两件事:
- Look up or generate the designated proxy class.(查找或生成指定的代理类)
- Invoke its constructor with the designated invocation handler.(使用指定的调用处理程序调用它的构造函数)
参考文章
http://blog.csdn.net/jiankunking/article/details/52143504