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动态代理

posted @ 2022-04-13 15:18  lifelikeplay  阅读(37)  评论(0编辑  收藏  举报