摘要:静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由在运行时动态生成的而非预存在于任何一个文件中。
代理:设计模式
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
java.lang.reflect.Proxy:Proxy 的静态方法
// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器 static InvocationHandler getInvocationHandler(Object proxy) // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象 static Class getProxyClass(ClassLoader loader, Class[] interfaces) // 方法 3:该方法用于判断指定类对象是否是一个动态代理类 static boolean isProxyClass(Class cl) // 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例 static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
ava.lang.reflect.InvocationHandler:InvocationHandler 的核心方法
// 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象 // 第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行 Object invoke(Object proxy, Method method, Object[] args)
java.lang.ClassLoader:这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。
代码实例Client.java
public class Client { public static void main(String[] args) { LogHandler logHandler = new LogHandler(); UserManager userManager = (UserManager)logHandler.newProxyInstance(new UserManagerImpl()); userManager.addUser("0001", "User1"); } }
myHandler.java
public class MyHandler implements InvocationHandler { private Object targetObject; public Object newProxyInstance(Object targetObject) { this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { StringBuilder sb = new StringBuilder(); for (Object o: args){ sb.append(o.toString()); sb.append(","); } sb.setLength(sb.length()-1); System.out.println("invoke: start "+method.getName()+"("+ sb.toString()+ ")"); Object ret = null; try { ret = method.invoke(targetObject, args); System.out.println("invoke: success"); }catch(Exception e) { System.out.println("invoke: error"); e.printStackTrace(); throw e; } return ret; } }
UserManager.java
public interface UserManager { public void addUser(String userId, String userName); }
UserManagerImpl.java
public class UserManagerImpl implements UserManager { public void addUser(String userId, String userName) { System.out.println("addUser: function call"); } }参考资料
Java 动态代理机制
利用动态代理的 Java 验证
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65716.html
摘要:动态代理有多种不同的用途,例如,数据库连接和事务管理用于单元测试的动态模拟对象其他类似的方法拦截。调用序列和下面的流程类似单元测试动态对象模拟利用动态代理实现单元测试的动态存根代理和代理。框架把包装成动态代理。 使用反射可以在运行时动态实现接口。这可以使用类java.lang.reflect.Proxy。这个类的名称是我将这些动态接口实现称之为动态代理的原因。动态代理有多种不同的用途,...
摘要:反射使用类对象提供的基本元数据,能从类对象中找出方法或字段的名称,然后获取表示方法或字段的对象。常见的反射手段有反射和反射。以之前的反射为例其中指定了方法的返回类型,其实不止如此。 Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类 在运行时构造任意一个类的对象 在运行时判断任意一个类所具有的成员变量和方法 在运行时调用任意一个对象的方法 生成动态代理 很多框架...
摘要:相比硬编码,反射要复杂的多,但其给我们带来了更大的灵活性。实际上构造函数也是类的静态方法,因此使用关键字创建类的新对象也会被当做对类的静态引用,从而触发类加载器对类的加载。基础基础主要是为反射提供通用特性的接口或基类。 1. Java类型系统 获取Java类型系统,主要有两个方式:一种是传统的RTTI(Run-Time Type Identification),它假定我们在编译时已经知...
摘要:接口与类型信息关键字的一种重要目标就是允许程序员隔离构件,进而降低耦合性。如果你编写接口,那么就可以实现这一目标,但是通过类型信息,这种耦合性还是会传播出去接口并非是对解耦的一种无懈可击的保障。 点击进入我的博客 运行时类型信息使得你可以在运行时发现和使用类型信息,主要有两种方式: 传统的RTTI,它假定我们在编译时已经知道了所有的类型; 反射机制,它允许我们在运行时发现和使用类的...
阅读 1614·2021-11-16 11:41
阅读 2389·2021-11-08 13:14
阅读 3042·2019-08-29 17:16
阅读 3045·2019-08-29 16:30
阅读 1799·2019-08-29 13:51
阅读 307·2019-08-23 18:38
阅读 3197·2019-08-23 17:14
阅读 592·2019-08-23 15:09