JDK的中实现动态代理,需要用到java反射包中Proxy类,和InvocationHandler接口
使用Proxy创建的代理,本质上是面向接口的代理,是对接口的实现。
我们通常说的为目标对象创建一个代理对象,前提就是需要目标对象实现接口,对目标对象的方法增强,本质上是代理对象对接口中对应方法的实现。
使用示例
1、先确定一个目标类Librarian,实现BookService接口,重写其中方法。
package org.example.proxy;
import org.example.domain.Book;
import org.example.service.BookService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Librarian implements BookService {
private Map<String, Book> books = new HashMap<>();
public void addBook(Book book) {
String name = book.getBookName();
if (this.books.containsKey(name)) {
this.books.put(name, book);
}
}
@Override
public List<Book> getAllBooks() {
System.out.println("这里是 " + getClass().getName() + " 的getAllBooks方法");
return new ArrayList<>(books.values());
}
@Override
public Boolean updateBookMessage(Book book) {
return true;
}
}
2、创建一个InvocationHandler实现类,也就是调用处理器,负责代理方法的实现。
package org.example.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class JdkProxy implements InvocationHandler {
//这里引入一个对象target,和他建立关联,后续对他的方法实现增强。
//当然如果后面invoke方法的实现与该对象无关,此处可以不引入。
private Object target;
public JdkProxy(Object target) {
this.target = target;
}
/**
* @param proxy 代理对象
* @param method 代理方法
* @param args 方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//这里所做的增强,实际只是输出一行文案,后面依旧是调用了目标对象的方法。
System.out.println("这里是代理方法");
return method.invoke(target, args);
}
}
3、创建一个JdkProxyFactory类,提供生产代理对象的方法。
package org.example.proxy.jdk;
import org.example.domain.Book;
import org.example.service.BookService;
import java.lang.reflect.Proxy;
public class JdkProxyFactory {
public Object getProxy(Object targetObject) {
ClassLoader classLoader = targetObject.getClass().getClassLoader();
Class<?>[] interfaces = targetObject.getClass().getInterfaces();
JdkProxy jdkProxy = new JdkProxy(targetObject);
//该方法接受三个参数:代理类的类加载器、代理类要实现的接口、InvocationHandler对象
return Proxy.newProxyInstance(classLoader, interfaces, jdkProxy);
}
public static void main(String[] args) throws NoSuchMethodException {
//设置系统参数,生成代理类的字节码文件(也可以在启动时以虚拟机参数的形式输入)
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Book book = new Book();
book.setBookName("战争与和平");
Librarian librarian = new Librarian();
librarian.addBook(book);
//调用普通对象方法
librarian.getAllBooks();
//调用代理对象方法
JdkProxyFactory jdkProxyFactory = new JdkProxyFactory();
BookService librarianProxy = (BookService) jdkProxyFactory.getProxy(librarian);
librarianProxy.getAllBooks();
}
}
运行以下实例代码main方法,结果如下,符合预期。
原理
直接进入Proxy.newProxyInstance方法:
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
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对象,如果没有则使用ProxyClassFactory类创建
具体到ProxyClassFactory#apply方法中,先根据接口生成代理类字节码数组,然后调用native方法defineClass0创建Class对象。
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取含InvocationHandler类型参数的构造器
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});
} 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);
}
}
总结:
1、先在缓存中找代理类Class对象,如果没有则使用ProxyClassFactory类创建,创建后放入缓存;
具体到ProxyClassFactory#apply方法中,先根据接口生成代理类字节码数组,然后调用native方法defineClass0创建Class对象。
2、拿到代理类Class对象,反射获取构造函数(参数类型为InvocationHandler),然后实例化代理对象。
生成的代理类字节码文件如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.List;
import org.example.domain.Book;
import org.example.service.BookService;
public final class $Proxy0 extends Proxy implements BookService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m4;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final Boolean updateBookMessage(Book var1) throws {
try {
return (Boolean)super.h.invoke(this, m3, new Object[]{var1});
} 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 List getAllBooks() throws {
try {
return (List)super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("org.example.service.BookService").getMethod("updateBookMessage", Class.forName("org.example.domain.Book"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("org.example.service.BookService").getMethod("getAllBooks");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
代理类$Proxy0继承Proxy类,实现了传入的BookService接口;
构造方法中调用了父类Proxy的含参构造方法,对InvocationHandler成员赋值;
静态代码块中初始化了要实现的方法,方法内部调用super.h.invoke,执行InvocationHandler的invoke方法。