Java代理和动态代理机制分析和应用
一、概述
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。根据代理类的**生成时间不同**可以将代理分为静态代理和动态代理两种。
二、代理的优点
a.隐藏委托类的实现,调用者只需要和代理类进行交互即可。
b.解耦,在不改变委托类代码情况下做一些额外处理,比如添加初始判断及其他公共操作。
三、应用场景
代理的使用场景很多,struts2中的 action 调用, hibernate的懒加载, spring的 AOP无一不用到代理。总结起来可分为以下几类:
- 在原方法执行之前和之后做一些操作,可以用代理来实现(比如记录Log,做事务控制等)。
- 封装真实的主题类,将真实的业务逻辑隐藏,只暴露给调用者公共的主题接口。
- 在延迟加载上的应用。
四、静态代理
所谓静态代理也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在**运行前就确定了**。
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
另外,如果要按照上述的方法使用代理模式,那么真实角色(委托类)必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色(委托类),该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。
五、动态代理
在java的动态代理API中,有两个重要的类和接口,一个是 **InvocationHandler(Interface)**、另一个则是 **Proxy(Class)**,这一个类和接口是实现我们动态代理所必须用到的。
1)InvocationHandler(Interface)
InvocationHandler是负责连接代理类和委托类的中间类必须实现的接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
InvocationHandler 的核心方法
Object invoke(Object proxy, Method method, Object[] args)
- proxy 该参数为代理类的实例
- method 被调用的方法对象
- args 调用method对象的方法参数
该方法也是InvocationHandler接口所定义的唯一的一个方法,该方法负责集中处理动态代理类上的所有方法的调用。调用处理器根据这三个参数进行预处理或分派到委托类实例上执行。
2)Proxy(Class)
Proxy是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
Proxy 的静态方法
static InvocationHandler getInvocationHandler(Object proxy)
该方法用于获取指定代理对象所关联的调用处理器static Class getProxyClass(ClassLoader loader, Class[] interfaces)
该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象static boolean isProxyClass(Class cl)
该方法用于判断指定类对象是否是一个动态代理类 static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h)
- loader 指定代理类的ClassLoader加载器
- interfaces 指定代理类要实现的接口
- h: 表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
使用Java 动态代理的两个重要步骤
- 通过实现 InvocationHandler 接口创建自己的调用处理器;
通过为Proxy类的newProxyInstance方法指定代理类的ClassLoader 对象和代理要实现的interface以及调用处理器InvocationHandler对象 来创建动态代理类的对象;
动态代理的优缺点
优点
1.动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。
2.动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。
缺点
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
还没有评论,来说两句吧...