java java 代理:java动态代理和静态代理 Acting 2024-11-14 2024-11-14 动态代理:类加载器,上下文加载器, 代理模式,是一种结构性设计模式,通过创建一个代理对象来控制对原有对象的访问。一般的,代理模式中有两个角色,代理角色和真实角色。代理类负责代理真实类,为真实类提供访问控制的功能,真实类其实是完成具体的业务逻辑。
所以,代理的主要目的就是
实现代理一般有两种实现方式:静态代理 和动态代理。
静态代理 在编译时,代理类已经被确定,需要事先手写一个代理类。
public interface Player { void loadVideo (String filename) ; } public class VPlayer implements Player { @Override public void loadVideo (String filename) { System.out.println("加载MP4视频文件:" +filename); } } public class VPlayerProxy implements Player { private Player player; public VPlayerProxy (Player player) { this .player = player; } @Override public void loadVideo (String filename) { player.loadVideo(filename); } } public class Client1 { public static void main (String[] args) { Player vplay=new VPlayer (); proxy.loadVideo("aaa.mp4" ) System.out.println(); Player proxy=new VPlayerProxy (vplay); proxy.loadVideo("aaa.mp4" ); } }
动态代理 在运行时动态的根据需求生成代理类。其中代理类有两种实现方式:
java自带 java.lang.reflect.Proxy 类 (本文将重点介绍这种方法)
开源的高性能代码生成包 CGlib
JDK动态代理
创建实现InvocationHandler接口的代理工厂:在调用Proxy类的静态方法newProxyInstance时,会动态的生成一个代理类。该代理类实现了目标接口,并且持有一个InvocationHandler类型的引用
InvocationHandler接口:InvocationHandler是一个接口 他只有一个方法 invoke。在代理对象的方法被调用时,JVM会自动调用代理类的invoke方法
调用代理对象的方法:当代理对象的方法被调用时,JVM会自动调用代理类的invoke方法。可以添加调用代理类的invoke方法,并将被调用的方法名 参数等信息传递给该方法。
invoke方法调用:在invoke方法中,通过反射机制调用目标对象的方法,并返回方法的返回值,在调用目标对象的方法前后,可以执行额外的逻辑。
public class JDKProxyFactory implements InvocationHandler { private Object object; public JDKProxyFactory (Object object) { this .object = object; } @SuppressWarnings("unchecked") public <T> T getProxy () { return (T) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), object.getClass().getInterfaces(), this ); } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { Object result = null ; if ("loadVideo" .equals(method.getName())) { result=method.invoke(object, args); } if ("playVideo" .equals(method.getName())) { System.out.println("前置增强" ); result=method.invoke(object, args); System.out.println("后置增强" ); } return result; } } public class Client2 { public static void main (String[] args) { Player player=new VPlayer (); Player proxy=new JDKProxyFactory (player).getProxy(); proxy.loadVideo("aaa.mp4" ); proxy.playVideo("aaa.mp4" ); } }
概括 代理的优点
隐藏了原始对象的实现细节,使得客户端不需要了解原始对象的实现
可以原始对象的基础上添加额外的功能,例如,缓存,安全验证,日志
控制对原始对象的访问,保护原始对象不会被非法访问
缺点:
增加了代理层,请求处理速度变慢
引入代理类增加了系统复杂程度,增加了学习成本
适应场景
当创建和初始化一个对象的开销很大的时候,可以使用代理模式延迟对象的实例化
日志记录,代理模式在真实的对象方法执行前后进行日志记录,实现日志记录调优
缓存代理,当客户端请求某个对象时,代理对象先检查缓存中是否存在该对象,如果存在则直接返回 否则创建新的对象并缓存起来,提高系统性能