Java中通过反射实现代理Proxy代码实例
1.实现一个简易的代理类
java实现代理可以通过java.lang.reflect.Proxy接口结合java.lang.reflect.InvocationHandler来实现
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class ProxyHandler implements InvocationHandler { private UserService object; public ProxyHandler() { this.object = new UserServiceImpl(); } public UserService newProxyInstance(){ return (UserService) Proxy.newProxyInstance(this.object.getClass().getClassLoader(), this.object.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("预处理"); Object object = method.invoke(this.object, args); if(object instanceof Person) { ((Person) object).setName("姓名:" + ((Person) object).getName()); } System.out.println("后处理"); return object; } }
通过如下方法调用生成代理的对象
public class Test { public static void main(String[] args) { ProxyHandler proxyHandler = new ProxyHandler(); //生成代理类初始化被代理类 UserService userService = proxyHandler.newProxyInstance(); //生成代理实例 System.out.println(userService.getUserInfo(1).getName()); //调用被代理方法 } }
此时代理类内自定义的invoke方法将会在被代理方法执行前后执行自定义的操作
控制台输出结果
预处理
后处理
姓名:libiyi
2.Proxy.newProxyInstance()解析
如下是源码
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); } /* * 从缓存中获取到代理类 */ Class<?> cl = getProxyClass0(loader, intfs); try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } 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); } }
从如上代码可见,首先需要获取代理类,然后再获取到代理类构造器,最后使用构造器生成代理类实例。
关键的代理类获取在getProxyClass0方法、和getConstructor中
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());
在getProxyClass0方法中,使用了关键的WeakCache类,其中的结构是ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>>。 最外层map的key是通过classLoader得出的CacheKey类型,value是一个map,其中key为由classLoader和interfaces[]共同得出的一个Key,value是缓存的代理类。
到此这篇关于Java中通过反射实现代理Proxy代码实例的文章就介绍到这了,更多相关Java反射实现代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Java中的InputStreamReader和OutputStreamWriter源码分析_动力节点Java学院整理
本文通过示例代码给大家解析了Java中的InputStreamReader和OutputStreamWriter知识,需要的的朋友参考下吧2017-05-05SpringBoot + MapStruct 属性映射工具的使用详解
MapStruct 是一个代码生成器,简化了不同的 Java Bean 之间映射的处理,所谓的映射指的就是从一个实体变化成一个实体。接下来通过本文给大家介绍SpringBoot + MapStruct 属性映射工具的使用,需要的朋友可以参考下2021-09-09解决spring.thymeleaf.cache=false不起作用的问题
这篇文章主要介绍了解决spring.thymeleaf.cache=false不起作用的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-06-06Springboot+SpringSecurity+JWT实现用户登录和权限认证示例
这篇文章主要介绍了Springboot+SpringSecurity+JWT实现用户登录和权限认证示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-06-06SpringMVC中MultipartFile转File的两种方式
在spring上传文件中,一般都使用了MultipartFile来接收,但是有需要用到File的地方,本文主要介绍了SpringMVC中MultipartFile转File的两种方式,感兴趣的可以了解一下2022-04-04
最新评论