最近笔者在深入了解一些开源框架,比如Spring,mybatis这些框架,去阅读源码学习作者的一些好的设计思路和写法。通过阅读源码你会学到很多大神的编程思想,其中有很多很好的设计模式。看过很多源码的话,你会发现很多地方都采用了代理设计模式来使得框架的灵活性开发,今天主要根据JDK的动态代理来介绍下这个代理模式。
首先做个小的铺垫,很多描述代理模式的时候会用两个名词 代理对象 和 目标对象。
代理对象代理的就是目标对象。这俩的关系在程序里不是恒定的。
就比如 一种恋爱关系 A->B->C A暗恋B B是被暗恋的, 但是B暗恋C 相对有C来说C是被暗恋的,就是大家清楚这种关系 是相对的,不是绝对的。
静态代理的体现在 继承和聚合-接口的形式
/**
* 定义一个基础类
*/
public class BaseMapper {
//基础类的查询方法
public void select(){
}
}
//定义一个类实现这个方法的查询方法
public class QueryMapper extends BaseMapper {
@Override
public void select() {
System.out.println("查询方法");
}
}
//定义一个代理类去继承你想代理的方法
public class ProxyMapper extends QueryMapper{
@Override
public void select() {
System.out.println("代理方法");
super.select();
}
}
我们测试下
public static void main(String[] args) {
//正常的创建调用查询方法
BaseMapper queryMapper = new QueryMapper();
queryMapper.select();
System.out.println("=====================");
//代理的形式调用方法
BaseMapper proxyMapper = new ProxyMapper();
proxyMapper.select();
}
//打印出来
查询方法
=====================
代理方法
查询方法
缺点:这种继承的形式需要写大量的继承关系,创建大量的类,代理类过多
/**
* 基础接口
*/
public interface BaseMapper {
//定义查询接口
void select();
}
一个实现类
/**
* 搜索方法
*/
public class SelectMapper implements BaseMapper {
@Override
public void select() {
System.out.println("select * from xxx");
}
}
聚合-接口形式实现静态代理,创建一个代理对象需要那些条件。
- 代理对象要和目标对象实现同一个接口
- 代理对象存在一个属性接收目标对象
- 代理对象的构造方法注入目标对象
创建一个代理对象,
/**
* 代理对象
*/
public class ProxyMapper implements BaseMapper {
private BaseMapper baseMapper ;
public ProxyMapper(BaseMapper baseMapper) {
this.baseMapper = baseMapper;
}
@Override
public void select() {
System.out.println("代理方法");
baseMapper.select();
}
}
我们调用下
public static void main(String[] args) {
//正常的创建调用查询方法
BaseMapper queryMapper = new SelectMapper();
queryMapper.select();
System.out.println("=====================");
//代理的形式调用方法
BaseMapper proxyMapper = new ProxyMapper(queryMapper);
proxyMapper.select();
}
打印:
select * from xxx
=====================
代理方法
select * from xxx
如果说我们要在查询方法之前先做条数统计count的功能 ,那么我们需要新增代理对象
public class CountMapper implements BaseMapper {
private BaseMapper baseMapper ;
public CountMapper(BaseMapper baseMapper) {
this.baseMapper = baseMapper;
}
@Override
public void select() {
//统计方法
System.out.println("统计方法");
baseMapper.select();
}
public static void main(String[] args) {
//正常的创建调用查询方法
BaseMapper queryMapper = new SelectMapper();
queryMapper.select();
System.out.println("=====================");
//代理的形式调用方法
BaseMapper proxyMapper = new ProxyMapper(queryMapper);
proxyMapper.select();
System.out.println("=====================");
//先执行 代理->新增统计方法->查询
BaseMapper proxy = new ProxyMapper(new CountMapper(new SelectMapper()));
proxy.select();
}
打印:
select * from xxx
=====================
代理方法
select * from xxx
=====================
代理方法
统计方法
select * from xxx
很明显,我们这种聚合-接口的形式,能够很灵活去在目标对象的方法上 做各种的扩展。上面这个例子,也可以看出代理对象和目标对象的关系是相对的。
但是还是会存在大量的代码量,所以人们开始思考如何能够动态的生成满足我们需要的代理对象来帮我们实现我们想要的功能。
小总结下:仔细看来这些静态代理的形式,会发现这是一种编程的多态运用,多态的定义很广,也很灵活。
在JDK的java.lang.reflect.Proxy类newProxyInstance方法
/**
* 返回指定接口的代理类的实例,该实例将方法调用分派到指定的调用处理程序。
* @param loader 类加载器
* @param interfaces 接口集
* @param h 将方法的调用分派给调用处理程序
* @return 返回一个代理对象
*/
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h){
}
我们试着去调用这个方法生成一个代理对象
首先我们先定义一个接口UserDao
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Select {
String value() default "";
}
public interface UserDao {
@Select("select * from xxx")
String select();
}
我们写一个方法去调用Proxy的生成代理类方法
public class MapperFactory {
public static Object getMapper(Class interfaces) {
//interfaces 为目标对象实现的多个接口
Class[] classes = {interfaces};
//获取接口集的代理对象
Object o = Proxy.newProxyInstance(MapperFactory.class.getClassLoader(),//类加载器
classes,//接口集
new MapperInvocationHandler());//指定的调用处理程序
return o;
}
}
//创建一个实现InvocationHandler接口的实现类 MapperInvocationHandler
/**
* 模拟mybatis框架的mapper接口动态代理实现
* */
public class MapperInvocationHandler implements InvocationHandler {
//invoke 在代理对象中调用该方法 转入相应的目标对象方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//我们自定义一些方法的实现 和 前后增强
System.out.println("链接数据库");//实现一个数据库链接的操作呀
Select annotation = method.getAnnotation(Select.class);
System.out.println(annotation.value());//处理一下方法的注解逻辑呀
return method.getReturnType().newInstance();//根据方法的返回对象 可以自定义
}
}
}
我们调用一下
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
UserDao userDao = (UserDao) MapperFactory.getMapper(UserDao.class);
userDao.select();
}
打印:
链接数据库
select * from xxx
在调用Proxy.newProxyInstance方法后,内存中会注入一个代理对象,这个代理对象实现了你前面传入的所有interfaces[] 接口方法。
这个代理对象是存在内存中的,不是我们能看到的一个.java文件或者一个.class文件。
Mybatis框架的设计思路就是通过代理的形式来处理mapper接口。
我们的这种调用是模仿mybatis中的引用,是通过代理对象来实现mapper接口;
接下来我们来模仿Spring-aop的动态代理,他是根据目标对象来做代理增强的。
//创建一个实现类 实现UserDao.select方法
public class UserDaoImp implements UserDao {
@Override
public String select() {
System.out.println("实现类方法");
return "实现imp";
}
}
我们要对这个UserDaoImp.class类做代理
首先指定方法调用处理程序 InvocationHandler
/**
* 模拟Spring-aop形式的动态代理实现
*/
public class AopInvocationHandler implements InvocationHandler {
private Object target;
public AopInvocationHandler(Object object) {
this.target = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("aop-before method");//@before 前置增强 方法
Object invoke = method.invoke(target, args);//目标对象自身方法逻辑和处理结果
System.out.println("aop-after method");//@after 后置增强 方法
return invoke;
}
}
//模拟的工厂类
public class AopProxyFactory {
public static Object getMapper(Object target) {
//interfaces 为目标对象实现的多个接口
Class[] classes = target.getClass().getInterfaces();//获取对象所有的接口class集合
//获取接口集的代理对象
Object o = Proxy.newProxyInstance(AopProxyFactory.class.getClassLoader(),//类加载器
classes,//接口集
new MapperInvocationHandler(target));//目标对象传入 指定的调用处理程序
return o;
}
}
我们来调用他
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
UserDao userDao = (UserDao) AopProxyFactory.getMapper(new UserDaoImp());
userDao.select();
}
打印:
aop-before method
实现类方法
aop-after method
这种我们是以目标对象 UserDaoImp 生成的代理对象 $Proxy0
本质上还是调用目标对象的select()方法,但是可以在方法的前后做自己的逻辑增强处理。
至于Proxy.newProxyInstance方法中是如何生成代理对象的让我们走进方法的源码。
笔者会待大家走一下方法的主线,当然很多细节还需要读者去自己深入的了解下,看源码一定要先弄清方法的主线。
//关键类
package java.lang.reflect.Proxy;
/**
* 返回指定接口的代理类的实例,该实例将方法调用分派到指定的调用处理程序。
* @param loader 类加载器
* @param interfaces 接口集
* @param h 将方法的调用分派给调用处理程序
* @return 返回一个代理对象
*/
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) throws IllegalArgumentException{
Objects.requireNonNull(h);//InvocationHandler不能传null
final Class<?>[] intfs = interfaces.clone();
//获取代理对象class com.sum.proxy.$Proxy0
Class<?> cl = getProxyClass0(loader, intfs);
//获取代理对象的构造方法 生成一个有参的构造方法 &Proxy0(InvocationHandler h)
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;
}
});
}
//实例化 代理对象 &Proxy0(InvocationHandler h)
return cons.newInstance(new Object[]{h});
}
方法
Class<?> getProxyClass0(ClassLoader loader,Class<?>… interfaces);
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// 有个缓存机制,如果存在就返回代理对象
// 否则通过ProxyClassFactory创建一个代理class
return proxyClassCache.get(loader, interfaces);
}
proxyClassCache 属性;
//a cache of proxy classes
//代理类的缓存容器
WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
WeakCache.get(K key, P parameter) ; 缓存容器的get方法
// p interfaces[]
public V get(K key, P parameter) {
Object cacheKey = CacheKey.valueOf(key, refQueue);
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;
}
}
// 上面都不用在意 硬要理解的话 可以理解成 程序在帮我们申请内存 初始化容器和数据记录
//第一个很关键的方法
//KeyFactory.apply(ClassLoader classLoader, Class<?>[] interfaces);
//subKey是把interfaces封装在里面
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
//WeakCache.Factory类
Factory factory = null;
//自旋
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
//类型可能是一个 Factory 或者 CacheValue<V>实例
//第三步 我们调用这个 supplier 的get方法,这个时候 supplier被第二步赋值
// 等同于调用 Factory.get()方法
V value = supplier.get();
if (value != null) {
return value;
}
}
//第一步 创建一个工厂
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被工厂赋值
supplier = factory;
}
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
supplier = factory;
} else {
supplier = valuesMap.get(subKey);
}
}
}
}
第三步调用 方法 WeakCache.Factory类实现了Supplier.get方法
@Override
public synchronized V get() { // serialize access
// 自身检查
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
//返回null 重新加入 外层自旋
return null;
}
// create new value
V value = null;
try {
//最关键的方法 通过ProxyClassFactory创建一个代理class
//调用 Class<?> apply(ClassLoader loader, Class<?>[] interfaces)
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // 创建失败 清除
valuesMap.remove(subKey, this);
}
}
// 断言
assert value != null;
return value;
}
}
//在内存中动态生成代理对象的类class
Class<?> apply(ClassLoader loader, Class<?>[] interfaces)
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
//循环接口class集合 主要做一些判断
for (Class<?> intf : interfaces) {
Class<?> interfaceClass = null;
try {
//拿到这个 接口的class
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
/*
* 判断这个class是一个接口
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
*判断这个接口是否重复
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
//*******开始处理一些代理对象相关的属性 **********
String proxyPkg = null; // 代理类的包路径 类似 package java.xxx.xxx
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* 记录非公共代理接口的程序包,以便在同一程序包中定义代理类。
* 验证所有非公共代理接口都在同一程序包中。
* 这个不在主流成中 一般不会进到循环里
**/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.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");
}
}
}
//处理代理类的 package 路径
if (proxyPkg == null) {
// 没有非公共代理的接口 我们采用 com.sun.proxy 包路径
// ReflectUtil.PROXY_PACKAGE = com.sun.proxy
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/**
* 处理proxyName代理类名
*/
long num = nextUniqueNumber.getAndIncrement();//获取编号
// 所有代理类名称的前缀 String proxyClassNamePrefix = "$Proxy"
// com.sun.proxy. + $Proxy + 0 当前的代理类的名称
String proxyName = proxyPkg + proxyClassNamePrefix + num;
//******生成指定的 代理类 class ********************
//调用 ProxyGenerator.generateProxyClass 生成代理类的字节码
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);
//调用神奇的JVM虚拟机的bean方法 将一个class byte[]字节 编译成内存对象
//private static native Class<?> defineClass0(ClassLoader loader, String name,byte[] b, int off, int len); 返回class
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}
}
调用 ProxyGenerator.generateProxyClass 生成代理类的字节码动态代理的核心方法
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
//生成构建器
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
//generateClassFile 获取class字节
final byte[] var4 = var3.generateClassFile();
//boolean saveGeneratedFiles = (Boolean)AccessController.doPrivileged(new GetBooleanAction(
"sun.misc.ProxyGenerator.saveGeneratedFiles"));
//这个boolean表示生成的代理对象是否保存到本地,因为这个类只是被加载到内存中,默认是不保存
if (saveGeneratedFiles) {
//开始写入操作通过流将 内存中的代理对象生成 .class文件
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 > 0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
} else {
var2 = Paths.get(var0 + ".class");
}
Files.write(var2, var4, new OpenOption[0]);
return null;
} catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}
//返回代理对象的字节
return var4;
}
generateClassFile方法处理代理对象字节
private byte[] generateClassFile() {
//这里的this是 ProxyGenerator 代理对象构造器
//添加 Object的 hashCode equals toString 方法
this.addProxyMethod(hashCodeMethod, Object.class);
this.addProxyMethod(equalsMethod, Object.class);
this.addProxyMethod(toStringMethod, Object.class);
Class[] var1 = this.interfaces;//目标对象的接口集
int var2 = var1.length;
int var3;
Class var4;
//将目标对象接口集的所有方法 添加到代理对象构造器中
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];//获取到其中一个接口
Method[] var5 = var4.getMethods();//获得接口中所有的方法集
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method var8 = var5[var7];//拿到方法集中的一个方法
this.addProxyMethod(var8, var4);//将方法添加到构造器中 var8=select()方法 var4 = UserDao这个接口对象
}
}
//拿到这个方法集合 这个集合就是上面处理好的所有的方法
Iterator var11 = this.proxyMethods.values().iterator();
List var12;
while(var11.hasNext()) {
var12 = (List)var11.next();
//检查返回类型
checkReturnTypes(var12);
}
Iterator var15;
//generateConstructor() 添加代理对象的构造方法
//这个面是写死的 代理对象的有参数 参数:InvocationHandler var1
this.methods.add(this.generateConstructor());
var11 = this.proxyMethods.values().iterator();
while(var11.hasNext()) {
var12 = (List)var11.next();
var15 = var12.iterator();
while(var15.hasNext()) {
//添加 Proxy方法 代理对象 默认继承Proxy类 包含 属性 protected InvocationHandler h;
ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
this.methods.add(var16.generateMethod());
}
}
this.methods.add(this.generateStaticInitializer());
//判断方法和属性的长度
if (this.methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
} else if (this.fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
} else {
//**************从这开始 将所有的方法写入********
this.cp.getClass(dotToSlash(this.className));
this.cp.getClass("java/lang/reflect/Proxy");
var1 = this.interfaces;
var2 = var1.length;
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
this.cp.getClass(dotToSlash(var4.getName()));
}
this.cp.setReadOnly();
//创建流
ByteArrayOutputStream var13 = new ByteArrayOutputStream();
DataOutputStream var14 = new DataOutputStream(var13);
//写入
var14.writeInt(-889275714);
var14.writeShort(0);
var14.writeShort(49);
this.cp.write(var14);
var14.writeShort(this.accessFlags);
var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
var14.writeShort(this.interfaces.length);
Class[] var17 = this.interfaces;
int var18 = var17.length;
for(int var19 = 0; var19 < var18; ++var19) {
Class var22 = var17[var19];
var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));
}
var14.writeShort(this.fields.size());
var15 = this.fields.iterator();
while(var15.hasNext()) {
ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();
var20.write(var14);
}
var14.writeShort(this.methods.size());
var15 = this.methods.iterator();
while(var15.hasNext()) {
ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();
var21.write(var14);
}
var14.writeShort(0);
//ByteArrayOutputStream 转成 byte[]字节
//我们去打印Var13可能会发现 他的内容类似一个编译后的class文件
return var13.toByteArray();
}
}
代理对象默认的generateConstructor()
private ProxyGenerator.MethodInfo generateConstructor() throws IOException {
//有参构造方法 唯一参数 InvocationHandler
ProxyGenerator.MethodInfo var1 = new ProxyGenerator.MethodInfo("<init>", "(Ljava/lang/reflect/InvocationHandler;)V", 1);
DataOutputStream var2 = new DataOutputStream(var1.code);
this.code_aload(0, var2);
this.code_aload(1, var2);
var2.writeByte(183);
var2.writeShort(this.cp.getMethodRef("java/lang/reflect/Proxy", "<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
var2.writeByte(177);
var1.maxStack = 10;
var1.maxLocals = 2;
var1.declaredExceptions = new short[0];
return var1;
}
再回到newProxyInstance方法 这个时候拿到了 cl
Class<?> cl = getProxyClass0(loader, intfs);
//关键类
package java.lang.reflect.Proxy;
/**
* 返回指定接口的代理类的实例,该实例将方法调用分派到指定的调用处理程序。
* @param loader 类加载器
* @param interfaces 接口集
* @param h 将方法的调用分派给调用处理程序
* @return 返回一个代理对象
*/
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) throws IllegalArgumentException{
Objects.requireNonNull(h);//InvocationHandler不能传null
final Class<?>[] intfs = interfaces.clone();
//获取代理对象class com.sum.proxy.$Proxy0
Class<?> cl = getProxyClass0(loader, intfs);
//获取代理对象的构造方法 生成一个有参的构造方法 &Proxy0(InvocationHandler h)
//我们获得$Proxy0 的构造方法 generateConstructor()生成的
// constructorParams = InvocationHandler h
final Constructor<?> cons = cl.getConstructor(constructorParams);
//实例化 代理对象 &Proxy0(InvocationHandler h)
return cons.newInstance(new Object[]{h});
}
我们跟过一遍就知道他代理代理的生成逻辑了,但是毕竟代理对象是在内存中,我们很难看到他的样子,如果存在.java或者.class文件是不是就更好理解了呢?
在源码的过程中 有过一个是否将代理对象保存到本地的判断,大家还记得吗?
我们可以开启他。
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
// saveGeneratedFiles = true 保存代理对象到磁盘 地址默认为 com.sum.proxy 目录下
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//这个时候 userDao 就不是 UserDaoImp 而是他的代理对象 $Proxy0
UserDao userDao = (UserDao) AopProxyFactory.getMapper(new UserDaoImp());
userDao.select();
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sun.proxy;
import com.example.spring2.proxy.UserDao;
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 UserDao {
//代理对象默认继承Proxy类
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
//父类Proxy属性 protected InvocationHandler h;
//构造方法
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
//静态块 获取到目标对象的方法
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
//获取到目标对象 UserDao的select方法
//Class.forName(String className).getMethod(String name, Class<?>... parameterTypes)
m3 = Class.forName("com.example.spring2.proxy.UserDao").getMethod("select");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
//目标对象的方法
public final String select() throws {
try {
//这就是为什么 代理对象可以和目标对象存在一样的功能。
//调用 InvocationHandler.invoke方法 传入目标对象的方法和入参
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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 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);
}
}
}
小总结下:代理是调用相同的方法,得到的处理逻辑可能一样,也可能不同,就是代理不一定是增强,很多现在人们说是增强方法,但是也可以是改变,改变这个方法。
就像 如果我们不去Object invoke = method.invoke(target, args);调用/目标对象自身方法逻辑 ,是不是也可以自己去书写他新的逻辑,返回同样的返回类型。所以我们出了代理增强,也是一种代理改变。
github: https://github.com/dxt1218/jdk-proxy
当然动态代理的实现有很多种,SpringAop中Cglib也可以实现动态代理,这个后续笔者可以再出一篇Cglib的动态代理的源码实现。
希望这篇文章能够有助于大家,有什么好的建议和疑问也可以留言交流,感谢阅读~~
本文实例讲述了php设计模式之策略模式。分享给大家供大家参考,具体如下: 星际...
ajax简介 AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),...
文章目录 环境 1、安装邮件功能--服务器上配置 2、配置邮件报警功能---服务器上...
【六】漏洞检测 1.Nessus 1.1 启动Nessus 2. Nmap 脚本引擎(NSE 2.1 Nmap 脚本存...
HLCA综合实验 一、实验要求 二、实验内容 1、进行IP地址规划及拓扑搭建 2、进行...
本文实例为大家分享了JS实现公告上线滚动效果的具体代码,供大家参考,具体内容...
在使用order by时,经常出现Using filesort,所以对于此类sql语句我们需要去尽力...
文章目录 关系数据库 关系数据库简介 关系数据结构及形式化定义 关系 关系模式 ...
微软将会在今年下半年发布的Windows10 21H2中,使用全新设计的UI界面,以改变Win...
前言 什么是流式传输? 流式传输是这一种以稳定持续流的形式传输数据的技术。 流...