前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >动态代理

动态代理

作者头像
星哥玩云
发布2022-09-14 20:33:28
2660
发布2022-09-14 20:33:28
举报
文章被收录于专栏:开源部署开源部署

1、动态代理概述

代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。 举例:春季回家买票让人代买,租房找中介 动态代理:在程序运行过程中产生的这个对象 如何让程序在运行过程中帮我们动态地产生这个对象呢?可以通过Java的反射实现。

为什么要用动态代理

​ 动态代理的目的是在不更改原有对象(目标对象)的基础上实现功能代码的增强

2、动态代理的种类

(1) JDK动态代理

(2)CGLIB动态代理

3、JDK动态代理

3.1、概述

JDK的动态代理是JDK自带的动态代理技术,所以使用JDK动态代理的时候不需要额外引入第三方的jar包!

JDK动态代理是对对象本身进行代理的一种技术!他是通过java.lang.reflect包下提供的一个Proxy类的newProxyInstance方法和一个InvocationHandler接口来实现动态代理对象的!

但JDK提供的代理只能针对实现接口的对象做代理!如果要对没有接口实现的类做代理的话就要用cglib了。

3.2、实现步骤

需求:给钢铁侠添加火箭助推器

1、创建接口(火箭助推器接口)

代码语言:javascript
复制
public interface Rocket {
	public void takeOff();
}

2、创建目标对象钢铁侠并实现火箭助推器接口

代码语言:javascript
复制
public class IronMan implements Rocket {

	@Override
	public void takeOff() {
		System.out.println("i can fly!!!");
	}

}

3、创建动态代理启用控制类,该类功能是对方法功能进行增强,该类实现InvocationHandler接口

代码语言:javascript
复制
 class MyInvocationHandler implements InvocationHandler{
	
	//目标对象
	Object obj;
	
	public MyInvocationHandler(Object obj) {
		super();
		this.obj = obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("火箭助推器被增强了");//增强的功能代码
		Object rst = method.invoke(obj, args);//执行目标对象方法
		return rst;
	}
	
}

4、创建目标对象,并通过Proxy代理类的newProxyInstance方法为其生成代理对象

代码语言:javascript
复制
public static void main(String[] args) {
		IronMan ir = new IronMan();//创建目标对象
		InvocationHandler h = new MyInvocationHandler(ir);//将目标对象传入控制器中等待被代理
		//生成代理对象
		Rocket proxy = (Rocket) Proxy.newProxyInstance(ir.getClass().getClassLoader(), ir.getClass().getInterfaces(), h );
		proxy.takeOff();
	}

4、CGLIB动态代理

4.1、概述

cglib:code generator library,代码生成库,他可以动态的生成字节码对象,可以凭空创建一个字节码对象。

4.2、CGLIB原理

jdk代理是对类的对象进行代理,而CGLIB代理是通过创建一个目标对象的子类的形式进行代理,也就是CGLIB在类的字节码阶段,就已经把增强的代码织入进去了,之后再用增强的字节码对象创建该类的子类对象,从而实现了动态代理,达到代码增强的目的!

所需Jar包

  • asm-2.2.3.jar
  • asm-commons-2.2.3.jar
  • asm-util-2.2.3.jar
  • cglib-nodep-2.1_3.jar

4.3、CGLIB动态代理实现步骤

1、生成一个字节码对象 ----> 该对象就是CGLIB凭空造出的字节码对象

2、设置字节码对象的父类 —> 该父类就是要增强的目标对象

3、通过生成的子类去增程父类方方法—>在重写的过程中调用父类的原方法(回调)

4、通过这个生成的字节码对象创建增强对象 --> 再去调用方法,该方法就被增强了

image20191220085826462.png
image20191220085826462.png

4.4、CGLIB代码增强演示

1、导包

image20191220090211397.png
image20191220090211397.png

2、创建目标对象(无序实现接口)

代码语言:javascript
复制
//目标对象(要增强的类)
public class SuperMan {
	public void fly(){
		System.out.println("i can fly!!!");
	}
}

3、创建用于回调增强的方法类

代码语言:javascript
复制
public class MyCallback implements MethodInterceptor {

	/*
	 * target:目标对象
	 * method:目标对象中的方法
	 * args:方法的实参列表
	 * met:代理对象中的方法(子类中的方法)
	 * 
	 * */
	@Override
	public Object intercept(Object target, Method method, Object[] args,
			MethodProxy met) throws Throwable {
		System.out.println("火箭助推器");
		return met.invokeSuper(target, args);//子类中的方法执行
	}

}

4、创建子类字节码对象,设置回调,实现增强

代码语言:javascript
复制
public static void main(String[] args) {
		Enhancer en = new Enhancer();//凭空创建字节码对象
		en.setSuperclass(SuperMan.class);//设置该字节码对象的父类是SuperMan
		Callback cb = new MyCallback();//创建用于增强的回调对象
		
		en.setCallback(cb);//设置子类字节码对象的回调方法
		
		SuperMan sm = (SuperMan) en.create();//创建代理对象
		sm.fly();//调用代理对象中代理的方法,该方法以被增强
		
	}

运行结果

image20191220091153546.png
image20191220091153546.png
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、动态代理概述
  • 2、动态代理的种类
  • 3、JDK动态代理
    • 3.1、概述
      • 3.2、实现步骤
      • 4、CGLIB动态代理
        • 4.1、概述
          • 4.2、CGLIB原理
            • 4.3、CGLIB动态代理实现步骤
              • 4.4、CGLIB代码增强演示
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档