代理模式:
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
代理分类:
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
一、静态代理
1.业务接口
public interface Account { void deposit(); //存款 void draw(); //取款 }
2.业务接口实现
public class AccountImpl implements Account { @Override public void deposit() { System.out.println("取款"); } @Override public void draw() { System.out.println("存款"); } }
3.代理类
public class AccountProxy implements Account { private Account account; public AccountProxy(Account account) { this.account = account; } @Override public void deposit() { System.out.println("取款前校验"); account.deposit(); System.out.println("取款后通知"); } @Override public void draw() { System.out.println("存款前校验"); account.draw(); System.out.println("存款后通知"); } }
4.测试调用
public class MainTest { public static void main(String[] args) { Account account = new AccountImpl(); Account accountProxy = new AccountProxy(account); accountProxy.deposit(); accountProxy.draw(); } }
观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。
二、动态代理
动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
(1).JDK动态代理
JDK动态代理中包含一个类和一个接口:
1.InvocationHandler接口:
package java.lang.reflect; public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
参数:
proxy - 被代理的对象。
method -要调用的方法。
args - 方法调用时所需的参数。
可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。
2.Proxy类:
package java.lang.reflect; public class Proxy implements java.io.Serializable { public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException {...} public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {...} public static boolean isProxyClass(Class<?> cl) {...} public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException {...} }
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h) throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例
例子:
1.业务接口
public interface Account { void deposit(); //存款 void draw(); //取款 }
2.业务接口实现
public class AccountImpl implements Account { @Override public void deposit() { System.out.println("取款"); } @Override public void draw() { System.out.println("存款"); } }
3.代理类
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class AccoutJDKDynProxy implements InvocationHandler { private Object targetObj; public Object getProxy(Object targetObj) { this.targetObj = targetObj; return Proxy.newProxyInstance(targetObj.getClass().getClassLoader(), targetObj.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; System.out.println("操作前验证"); method.invoke(targetObj, args); System.out.println("操作后通知"); return result; } }
4.测试调用
public class MainTest { public static void main(String[] args) { Account account = new AccountImpl(); AccoutJDKDynProxy proxy = new AccoutJDKDynProxy(); Account accountProxy = (Account) proxy.getProxy(account); accountProxy.deposit(); accountProxy.draw(); } }
但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。
(2).Cglib动态代理
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
1.业务接口
public interface Account { void deposit(); //存款 void draw(); //取款 }
2.业务接口实现
public class AccountImpl implements Account { @Override public void deposit() { System.out.println("取款"); } @Override public void draw() { System.out.println("存款"); } }
3.代理类
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class AccountCglibDynProxy implements MethodInterceptor { private Object targetObj; public Object getProxy(Object target) { this.targetObj = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.targetObj.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("操作前验证"); Object result = proxy.invokeSuper(obj, args); System.out.println("操作后通知"); return result; } }
4.测试调用
public class MainTest { public static void main(String[] args) { Account account = new AccountImpl(); AccountCglibDynProxy proxy = new AccountCglibDynProxy(); Account accountProxy = (Account) proxy.getProxy(account); accountProxy.deposit(); accountProxy.draw(); } }
相关推荐
1:静态代理出现的实际背景,静态代理时如何演化成动态代理 2: 动态代理demo 举例实际应用场景(载入数据库驱动的时候,使用AIDL与系统Servic进行通信) 3: 动态代理使用到基础理论:ClassLoader 加载.class字节码...
java动态代理实例 要想理解拦截器的知识 最好要先理解java动态代理这块
java动态代理 完整版 java动态代理 完整版 java动态代理 完整版 java动态代理 完整版 java动态代理 完整版
662.660.JAVA基础教程_动态代理与Java8新特性-代理模式与动态代理(662).rar
664.662.JAVA基础教程_动态代理与Java8新特性-动态代理举例(664).rar
Java 动态代理详解(学习资料);Java 动态代理详解(学习资料);Java 动态代理详解(学习资料);Java 动态代理详解(学习资料);Java 动态代理详解(学习资料);
Java动态代理机制详解_动力节点Java学院整理,动力节点口口相传的Java黄埔军校
665.663.JAVA基础教程_动态代理与Java8新特性-AOP与动态代理的举例(665).rar
对代理模式与Java动态代理类的理解说明
详见:https://blog.csdn.net/qq_37651267/article/details/90083914
668.666.JAVA基础教程_动态代理与Java8新特性-Lambda表达式使用举例(668).rar
适用于初探java动态代理模式,精简易懂。
JAVA静态代理和动态代理
自己总结的代理模式和Java中的动态代理模式,有源码
java动态代理 public class HireProxy implements InvocationHandler { //被代理的真实角色 private Object obj; public HireProxy(Object obj) { super(); this.obj = obj; } //第二个参数method,被...
java 动态代理 简单实例 新手看看
更好的了解java动态代理的原理!
Java实现动态代理的两种方式。 相对来说cglib更加方便。可以实现为实现接口的类(非final类)
java jdk 动态代理 演示demo
666.664.JAVA基础教程_动态代理与Java8新特性-Java8新特性内容概述(666).rar