• Java代理


    代理

    引入

    ​ 总结梳理下代理相关的知识点,按照设计模式之代理模式、静态代理、动态代理的思路展开

    代理模式

    ​ 设计模式中的一种,某些情况下客户不想直接访问对象,进而借助中介帮忙完成某项任务,这个中介对象就是代理。

    ​ 定义:某些原因需要给对象提供代理以控制对象的访问。访问对象不能直接引用目标,代理对象作为访问对象和目标对象间的中介。

    ​ 优点:在访问对象和目标对象间起到中介和保护目标的作用;扩展目标对象功能;访问对象和目标对象分离,降低耦合度

    ​ 缺点:导致类的数量增加;访问对象和目标对象间增加对象,请求速度变慢;增加系统复杂度

    ​ 客户要访问真实主题,通过代理的方式访问,代理内部会调用主题的请求方法,但同时在其前后执行增强方法,可以通过此方式控制或拓展真实主题的功能。

    代理模式:根据代理的创建时期进行划分

    ​ 动态代理:程序运行期间,工具类动态生成代理类的class字节码文件缓存在内存,运用反射机制实例化代理对象

    ​ 静态代理:自己手写代理

    应用场景

    ​ 无法或不想直接引用某个对象或访问某个对象困难,用代理对象访问。代理模式的主要目的:保护目标对象;增强目标对象

    • 远程代理:隐藏访问目标存在于不同地址的事实,方便客户端访问。例如网盘在我的电脑生成的虚拟影盘图标,实际访问的是网盘
    • 虚拟代理:要创建的目标对象开销大。如下载大文件,短时间无法完成,先用小比例虚拟对象替换,提升用户体验
    • 安全代理:控制不同类客户对真实对象的访问权限
    • 智能指引:调用目标对象时,代理部分额外处理功能,如计算真实对象的引用次数
    • 延迟加载:延迟目标的加载,提高系统性能。如hibernate存在属性和关联表的延迟加载

    lingxing_beijing-010

    静态代理

    ​ 手动代理类,实现目标类的接口,引入目标类的实例,重写接口方法内,调用目标类实例方法并进行增强。

    ​ 可以在不改变类的情况下,实现对类的增强。但所谓静态就是在创建代理类时,接口和被代理类y已确定下来,代理类就是只能代理一种类。实际开发过程中,有多个类和接口需要代理增强的时候,这样会产生大量的冗余和复杂性,故推荐使用动态代理

    动态代理

    ​ 程序运行时创建的代理方式称为动态代理。静态代理是程序运行前,已经编译完成。动态代理是在运行时根据Java代码中的‘指示’动态生成的。动态代理相较于静态代理优势是方便对所有代理类统一管理,若是使用静态代理则每个都需要生成代理,很麻烦。代理方式有两种:JDK动态代理(接口)和CGLIB动态代理(继承)

    ​ JDK动态代理:Java自动生成代理类class对象,保存在内存中,通过反射获取代理类的构造方法,进而创建代理类的实例对象

    public class RenterInvocationHandler<T> implements InvocationHandler{
    	//被代理类的对象
    	private T target;
    	
    	public RenterInvocationHandler(T target){
    		this.target = target;
    	}
    
    	/**
            * proxy:代表动态代理对象
            * method:代表正在执行的方法
            * args:代表调用目标方法时传入的实参
            */
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args)
    			throws Throwable {
    		//代理过程中插入其他操作
    		System.out.println("租客和中介交流");
    		Object result = method.invoke(target, args);
    		return result;
    	}
    }
    

    ​ CGLIB动态代理:也叫子类代理,通过在内存中构建一个子类,在子类用方法拦截的方式拦截所有父类方法的调用,然后加入自己的操作。因为使用的是继承,不能代理final类

    public class ProxyFactory<T> implements MethodInterceptor {
    
    	private T target;
    
    	public ProxyFactory(T target) {
    		this.target = target;
    	}
    
    	// 创建代理对象
    	public Object getProxyInstance() {
    		// 1.cglib工具类
    		Enhancer en = new Enhancer();
    		// 2.设置父类
    		en.setSuperclass(this.target.getClass());
    		// 3.设置回调函数
    		en.setCallback(this);
    		return en.create();
    	}
    
            //拦截方法
    	@Override
    	public Object intercept(Object obj, Method method, Object[] args,
    			MethodProxy methodProxy) throws Throwable {
    		System.out.println("开始事务...");
    
    		// 执行目标对象的方法
    		Object result = method.invoke(target, args);
    
    		System.out.println("提交事务...");
    		return result;
    	}
    }
    

    参考文章

    代理模式

    静态代理详解

    java动态代理

  • 相关阅读:
    10-多线程笔记-2-锁-3-Lock-4-工具类
    09-多线程笔记-2-锁-3-Lock-3-ReadWriteLock
    08-多线程笔记-2-锁-3-Lock-2-Lock
    07-多线程笔记-2-锁-3-Lock-1-AQS
    空闲时间无聊写的一个软著源代码文档生成器
    Centos7.x创建lvm
    cups API
    debezium 使用踩坑
    hive 行列转换
    mac 上docker 容器动态暴露端口
  • 原文地址:https://www.cnblogs.com/lifelikeplay/p/16140421.html
Copyright © 2020-2023  润新知