一,动态代理的作用
首先来看静态代理,静态代理包括三个角色,抽象角色,真实角色,代理角色。真实角色实现主要的业务逻辑;代理角色将真实角色封装,同时可以添加日志,缓存,权限管理等业务。静态代理将主要业务逻辑和其他业务分层次管理,降低了耦合,易于管理和维护。
当静态代理类中的方法越来越多,每个方法中的缓存等业务需要的重复代码越来越多,这时候就引入了动态代理。
所以动态代理的作用:对业务进行逻辑分层管理,降低耦合;减少了静态代理造成的代码冗余
二,动态代理的使用及原理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy {
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
InvocationHandler handler = new InvocationHandler() {
ProxyInstance instance = new ProxyInstance();
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("对" + method.getName() + "的额外操作");
return method.invoke(instance, args);
}
};
Interface1 obj = (Interface1) Proxy.newProxyInstance(Interface1.class.getClassLoader(),
new Class[] { Interface1.class, Interface2.class},
handler);
obj.method1();
@SuppressWarnings("unchecked")
Class<Interface1> class2 = (Class<Interface1>) Proxy.getProxyClass(Interface1.class.getClassLoader(),
new Class[] { Interface1.class, Interface2.class});
System.out.println(obj.getClass() == class2);
}
}
interface Interface1 {
void method1();
}
interface Interface2 {
void method2();
}
class ProxyInstance implements Interface1, Interface2 {
@Override
public void method2() {
System.out.println("method2");
}
@Override
public void method1() {
System.out.println("method1");
}
}
什么原理呢,直接点进去看jdk源码
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
SecurityManager sm = System.getSecurityManager();
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return newInstance(cons, ih);
}
});
} else {
return newInstance(cons, ih);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}
发现是获取一个Class类,然后通过构造器来实例化,再看一下获取Class类的方法,
/*
* Class的缓存机制:
* //loaderToCache Map<ClassLoader, Map<List<String>, Object>> weakHashMap
* //cache map<interfaces, class>
* //loaderToCache Map<ClassLoader, map<interfaces, class>>
*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
//接口的各种校验,省略
Class<?> proxyClass = null;
//interfaceNames 包含所有接口名称的list
List<String> key = Arrays.asList(interfaceNames);
Map<List<String>, Object> cache;
synchronized (loaderToCache) {
cache = loaderToCache.get(loader);
if (cache == null) {
cache = new HashMap<>();
loaderToCache.put(loader, cache);
}
}
//在缓存中寻找class,
synchronized (cache) {
//这个循环比较巧妙
do {
Object value = cache.get(key);
if (value instanceof Reference) {
proxyClass = (Class<?>) ((Reference) value).get();
}
if (proxyClass != null) {
// proxy class already generated: return it
return proxyClass;
} else if (value == pendingGenerationMarker) {
// proxy class being generated: wait for it
try {
cache.wait();
} catch (InterruptedException e) {
}
continue;
} else {
cache.put(key, pendingGenerationMarker);
break;
}
} while (true);
}
try {
String proxyPkg = null; // package to define proxy class in
//校验接口:非public接口必须在同一包下
//获取包路径
for (int i = 0; i < interfaces.length; i++) {
int flags = interfaces[i].getModifiers();
if (!Modifier.isPublic(flags)) {
String name = interfaces[i].getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
{
long num;
//同步
synchronized (nextUniqueNumberLock) {
num = nextUniqueNumber++;
}
String proxyName = proxyPkg + proxyClassNamePrefix + num;
//ProxyGenerator.generateProxyClass生成 类文件的二进制数据流,包含在byte数组中
//静态方法,那就可以直接调用次方法生成二进制数据流
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
try {
//通过btye数据,生产了class
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
// add to set of all generated proxy classes, for isProxyClass
proxyClasses.put(proxyClass, null);
} finally {
synchronized (cache) {
if (proxyClass != null) {
cache.put(key, new WeakReference<Class<?>>(proxyClass));
} else {
cache.remove(key);
}
cache.notifyAll();
}
}
return proxyClass;
}
Class类原来是在运行时生成的。
将生成的class类文件$proxy0反编译后得到如下
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 Interface1, Interface2
{
private static Method m1;
private static Method m3;
private static Method m4;
private static Method m0;
private static Method m2;
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 (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void method1()
throws
{
try
{
//执行方法是实际是将方法委托给InvocationHandler的invoke方法来执行
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void method2()
throws
{
try
{
this.h.invoke(this, m4, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
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
m3 = Class.forName("Interface2").getMethod("method1", new Class[0]);
m4 = Class.forName("Interface2").getMethod("method2", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
JDK中的动态代理原理,一目了然。
总结:动态代理(JDK)的原理是在运行时生成类字节码(proxy有缓存机制),然后通过反射获取实例。对实例中将方法的调用将委托给InvocationHandler的invoke方法。动态代理(JDK)只能对实现了接口的类生成代理,而不能针对类,因为生成的类需要继承proxy。