代理模式
理解
代理模式是一种设计模式,其意义是生成代理对象,通过控制代理对象来控制真实对象的访问
如rpc客户端中, 控制生成的消息代理对象(调用代理对象的方法),来完成对一次消息的封装,从而发送一个rpc请求
即完成在客户端封装一个调用服务端库对象,通过代理模式,控制代理对象,来完成实际的消息发送
代码
/**
* @Author: jiangtao
* @Date: 2021/10/8 18:57
*/
interface RPCServer {
// add为调用server中标识的方法名, x|y 为参数 (lsp)
int add(int x, int y);
}
class Proxy{
// 由于这是一个接口,所以就不需要传入target Object
public static <T> T getProxyService(Class<T> serviceClass){
ClassLoader loader = serviceClass.getClassLoader();
Class<?>[] interfaces = new Class[]{serviceClass};
Object o = java.lang.reflect.Proxy.newProxyInstance(loader, interfaces, (proxy, method, args) -> {
// 将调用方法转换为消息对象
// 发送消息到server
// 等待server返回结果
// 返回结果
// (可以讲以上步骤转换成一个Class)
return 1;
});
return (T) o;
}
}
class Test{
public static void main(String[] args) {
// 通过生成的代理对象,即可以调用方法
// 来控制真正对象访问
RPCServer rpcServer = Proxy.getProxyService(RPCServer.class);
int res = rpcServer.add(1,2);
}
}
静态代理和动态代理
静态代理需要手动生成代理对象
动态代理是在运行时自动创建代理对象并将其添加到JVM中
Java代理
Proxy
&InvocationHandler
-
上面代码
-
java.lang.reflect.Proxy.newProxyInstance
即为InvocationHandler
的唯一一个方法invoke
-
代理之后,返回代理对象,代理对象的每一个方法的调用都是
invoke
的调用,只是参数不同
拦截器
import java.lang.reflect.Method;
/**
* @Author: jiangtao
* @Date: 2021/10/8 19:39
*/
public interface Interceptor {
public boolean before(Object proxy, Object target, Method method, Object[] args);
public void after(Object proxy, Object target, Method method, Object[] args);
}
class InterceptorProxy{
// serviceClass每一次方法的调用,都将调用InvocationHandler.invoke
public static <T> T getProxyService(Class<T> serviceClass, Interceptor interceptor, Object target){
ClassLoader loader = serviceClass.getClassLoader();
Class<?>[] interfaces = new Class[]{serviceClass};
// proxy 代理对象, method 调用方法 , args 调用参数
Object o = java.lang.reflect.Proxy.newProxyInstance(loader, interfaces, (proxy, method, args) -> {
Object result = null;
if (interceptor == null) result = method.invoke(target, args);
if (interceptor.before(proxy, target, method, args)) result = method.invoke(target, args);
interceptor.after(proxy, target, method, args);
return result;
});
// 代理对象
return (T) o;
}
}
// 上述代理:将target所有方法调用,放到一个方法中,用不同逻辑调用
interface Client{
String sayHello(String name);
}
class TestProxy{
public static void main(String[] args) {
Client client = InterceptorProxy.getProxyService(Client.class, new Interceptor() {
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("---before---");
return true;
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("---after---");
}
}, new Client() {
@Override
public String sayHello(String name) {
System.out.println("hello~ " + name);
return name;
}
});
System.out.println(client.sayHello("me"));
}
}
自动生成的代理对象Class文件
// 通过反编译查看源代码
byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Client.class});
// JDK8之后不可在包外调用
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import test.Client;
public final class $Proxy0 extends Proxy implements Client {
private static Method m1;
private static Method m3;
private static Method m2;
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 String sayHello(String var1) throws {
try {
return (String)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 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("test.Client").getMethod("sayHello", Class.forName("java.lang.String"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
- 可见该Class继承Client接口,当该对象调用时,自动调用invoke方法(其中可以调用实际client方法)
手写Proxy&Invocationhanddler
package test;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: jiangtao
* @Date: 2021/10/9 17:29
*/
public interface MyInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
// Proxy
class MyProxy{
public static final String ln = "\r\n";
public static Object newProxyInstance(MyClassLoader classLoader, Class<?> [] interfaces, MyInvocationHandler h){
try {
// 动态生成源码.java文件
String src = generateSrc(interfaces);
// 文件输出到磁盘, 编译之后的Class文件的路径
String filePath = MyProxy.class.getResource("").getPath();
File f = new File(filePath + "$Proxy0.java");
FileWriter fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
// java文件转换为Class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable iterable = manager.getJavaFileObjects(f);
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
task.call();
manager.close();
// 编译生成的class文件加载到JVM中
Class proxyClass = classLoader.findClass("$Proxy0");
// 以参数的形式参入My
Constructor c = proxyClass.getConstructor(MyInvocationHandler.class);
f.delete();
// 返回字节码重组以后的代理对象
return c.newInstance(h);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public static String generateSrc(Class<?>[] interfaces){
StringBuilder builder = new StringBuilder();
builder.append(MyProxy.class.getPackage() + ";" + ln);
builder.append("import " + interfaces[0].getName() + ";" + ln);
builder.append("import java.lang.reflect.*;" + ln);
builder.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + ln);
builder.append("MyInvocationHandler h;" + ln);
builder.append("public $Proxy0(MyInvocationHandler h) { " + ln);
builder.append("this.h = h;" + ln);
builder.append("}" + ln);
for (Method m : interfaces[0].getMethods()){
Class<?> [] params = m.getParameterTypes();
StringBuffer paramNames = new StringBuffer();
StringBuffer paramValues = new StringBuffer();
StringBuffer paramClasses = new StringBuffer();
for (int i = 0; i < params.length; i++) {
Class clazz = params[i];
String type = clazz.getName();
// String paramName = toLowerFirstCase(clazz.getSimpleName());
String paramName = "var" + i;
paramNames.append(type + " " + paramName);
paramValues.append(paramName);
paramClasses.append(clazz.getName() + ".class");
if (i > 0 && i < params.length - 1){
paramNames.append(",");
paramClasses.append(",");
paramValues.append(",");
}
}
builder.append("public " + m.getReturnType().getName() + " " + m.getName() + "(" + paramNames.toString() + ") {" + ln);
builder.append("try {" + ln);
builder.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\", new Class[]{" + paramClasses.toString() + "});" + ln);
builder.append((hasReturnValue(m.getReturnType()) ? "return " : "") + getCaseCode("this.h.invoke(this, m, new Object[]{" + paramValues + "})", m.getReturnType()) + ";" + ln);
builder.append("}catch(Error _ex){}");
builder.append("catch(Throwable e){" + ln);
builder.append("throw new UndeclaredThrowableException(e);" + ln);
builder.append("}");
builder.append(getReturnEmptyCode(m.getReturnType()));
builder.append("}");
}
builder.append("}" + ln);
return builder.toString();
}
// 类型转换Mappings
private static Map<Class, Class> mappings = new HashMap<>();
static {
mappings.put(int.class, Integer.class);
}
// 返回值
public static String getReturnEmptyCode(Class<?> returnClass){
if (mappings.containsKey(returnClass)) return "return 0;";
else if (returnClass == void.class) return "";
else return "return null;";
}
// 类型转换
public static String getCaseCode(String code, Class<?> returnClass) {
// getName() 带有包名
// getSimpleName() 不带包名
// ((java.lang.Integer)100).intValue()
// if (mappings.containsKey(returnClass)) return "((" + mappings.get(returnClass).getName() + ")" + code + ")." + returnClass.getSimpleName() + "Value()";
return "(" + returnClass.getSimpleName() + ")" + code;
// return code;
}
// 是否有返回值
private static boolean hasReturnValue(Class<?> clazz){
return clazz != void.class;
}
// 首字母大写
private static String toLowerFirstCase(String src){
char[] chars = src.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
}
}
// MyClassLoader
class MyClassLoader extends ClassLoader{
private File classPathFile;
public MyClassLoader(){
// 获取当前Class的根目录
String classPath = MyClassLoader.class.getResource("").getPath();
this.classPathFile = new File(classPath);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// 当前class包名.类名
String className = MyClassLoader.class.getPackage().getName() + "." + name;
if (classPathFile != null){
File classFile = new File(classPathFile, name.replaceAll("\\.", "/") + ".class");
if (classFile.exists()){
FileInputStream in = null;
ByteArrayOutputStream out = null;
try{
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len;
while((len = in.read(buff)) != -1){
out.write(buff, 0, len);
}
// 在运行时刻从文件中调入Class
// 如果java.lang.NoClassDefFoundError SDKs中加入tools.jar(jdk1.8/lib)
return defineClass(className, out.toByteArray(),0,out.size());
}catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
// 放在这会class test.$Proxy0 cannot access its superinterface test.Person(public)
//interface Person{
// String sayHi(String name);
//}
class PersonProxy implements MyInvocationHandler{
private Person target;
public Person getInstance(Person person){
this.target = person;
Class<?> clazz = target.getClass();
return (Person) MyProxy.newProxyInstance(new MyClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before---");
Object res = method.invoke(this.target, args);
System.out.println("after----");
return res;
}
}
class FunctionTest{
public static void main(String[] args) throws IOException {
Person person = new PersonProxy().getInstance(new Person() {
@Override
public String sayHi(String name) {
System.out.println("hello " + name);
return name;
}
});
System.out.println(person.sayHi("me"));
}
}
// 可以手动删除生成文件
Proxy
源码梳理
- jdk8
- 返回代理对象
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
// Class
Class<?> cl = getProxyClass0(loader, intfs);
// 构造器
final Constructor<?> cons = cl.getConstructor(constructorParams);
// 实例
return cons.newInstance(new Object[]{h});
- 生成Class
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
-
proxyClassCache.get
-
如果代理类已经被类加载器缓存过,则直接复制一个返回,否则会通过ProxyClassFactory来创建代理
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
// 如果有supplier返回对应的class二进制文件
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)
// lazily construct a Factory
// 创建工厂
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
// 所以导致 supplier.get()可能是在读缓存, 可能是在获取数据
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
private final class Factory implements Supplier<V> {
@Override
public synchronized V get() {
// valueFactory为Proxy中的ProxyClassFactory
// apply为创建class文件
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
- 生成二进制文件
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
ProxyGenerator.generateProxyClass
public static byte[] generateProxyClass(final String name,
Class<?>[] interfaces,
int accessFlags)
{
ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
// 二进制文件的方法
final byte[] classFile = gen.generateClassFile();
// 是否保存在本地
if (saveGeneratedFiles) {
还有其他的代理,如cglib
由于本人理解能力有限,如有错误,请指出