0
点赞
收藏
分享

微信扫一扫

Java-JDK动态代理(AOP)


Java-JDK动态代理(AOP)

​​动态代理的应用SpringAOP实现原理​​

文章目录

  • ​​Java-JDK动态代理(AOP)​​
  • ​​什么是动态代理?​​
  • ​​知道动态代理能做什么 ?​​
  • ​​1.什么是代理​​
  • ​​使用代理模式的作用:​​
  • ​​实现代理的方式​​
  • ​​静态代理​​
  • ​​动态代理​​
  • ​​什么是动态代理​​
  • ​​静态代理和动态代理模式的对比​​
  • ​​动态代理中目标类即使很多​​
  • ​​动态代理:​​
  • ​​动态代理的介绍:​​
  • ​​动态代理的实现:​​
  • ​​JDK动态代理​​
  • ​​1) InvocationHandler`​​
  • ​​方法原型:​​
  • ​​`InvocationHandler `接口:​​
  • ​​2)Method类:​​
  • ​​3)Proxy类:​​
  • ​​实现动态代理的步骤:​​
  • ​​JDK动态代理执行流程​​
什么是动态代理?

使用JDK反射机制,创建对象的能力,创建的是代理类的对象,而不用你创建类,不用写java文件

动态:在程序执行时,调用JDK提供的方法才能创建代理类的对象

JDK动态代理,必须有接口,目标类必须实现接口,没有接口时需要使用cglib动态代理

知道动态代理能做什么 ?

在不改变原来的目标方法功能的前提下,可以在代理中增强自己的功能代码

1.什么是代理

代理:在我们生活之中就有体会,代购,中介,换IP,商家等等

使用代理模式的作用:

  1. 功能增强: 在你原有的功能上,增加了额外的功能,新增加的功能,叫做功能增强
  2. 控制访问: 代理类不上你访问目标…例如商家不让用户访问厂家

实现代理的方式

静态代理

  1. 代理类是自己手工写实现的,自己创建一个JAVA类,表示代理类
  2. 同时你所代理的目标类是确定的

**优点>>**实现简单 容易理解

缺点>> \当你的项目中.目标类和代理类很多的时候,有以下缺点

  1. 当目标类增加了,代理类可能也需要成倍的增加,代理类数量过多
  2. 当你的接口中功能增加了,或者修改了,会影响众多的实现类,厂家类,代理都需要修改,影响比较多

模拟一个用户购买u盘的行为。
用户是客户端类
商家:代理,代理某个品牌的u盘。
厂家:目标类。

​ 三者的关系: 用户(客户端)—商家(代理)—厂家(目标)
​ 商家和厂家都是卖u盘的,他们完成的功能是一致的,都是卖u盘。

实现步骤

  1. 创建一个接口,定义卖U盘的方法,表示你的厂家和商家做的事情
  2. 创建厂家类,实现1步骤的接口
  3. 创建厂家类,就是代理,也需要实现1步骤中的接口
  4. 创建客户端类,调用商家的方法买一个

代理类完成的功能:

  1. 目标类中的方法调用
  2. 功能增强

所属我们只有一个代理商,我们实际上可以写多个代理商,

动态代理

什么是动态代理

使用JDK的反射机制,创建对象的能力,创建的时代理类的对象.而不用我们创建类的文件.

什么叫动态?在程序执行时,调用JDK提供的方法才能创建代理类的对象

静态代理和动态代理模式的对比

静态代理中目标很多的时候,可以使用动态代理,避免静态代理的缺点

动态代理中目标类即使很多
  1. 代理类数量可以很少
  2. 当你修改了接口中的方法时…不会影响代理类
动态代理:

在执行过程中,使用了JDK的反射机制,创建代理类对象,并动态的指定要代理目标类

换句话说:动态代理是一种创建JAVA对象的能力,让你不用创建淘宝类,就能创建代理类对象,

在java中,要想创建对象

  1. 创建类文件,java文件编译为Class文件
  2. 使用构造方法,创建类的对象
动态代理的介绍:

1.动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的,动态代理不需要定义代理类的,java源文件

2.动态代理其就是JDK运行期间,动态创建Class字节码并加载到JVM

3.动态代理的实现运行常用两种方式:使用​​JDK​​​代理,与通过​​CGLlB​​动态代理。

动态代理的实现:
JDK动态代理

JDK动态代理(理解),使用java反射包的类和接口实现动态代理的功能

反射包​​java.lang.reflect​​​ 里面有三个类 : ​​InvocationHandler​​​ ,​​Method​​​, ​​Proxy​

  1. 反射: Method类,表示方法,类中的方法,通过method可以执行某个方法
  2. JDK动态代理的实现
    反射包 java.lang.reflect , 里面有三个类 :​​InvocationHandler , Method, Proxy.​
1) InvocationHandler`

​InvocationHandler​​​ 接口(调用对象); 就是一个方法​​invoke​​()

​invoke​​(): 表示代理对象要执行的功能代码, 要完成的功能就写在invoke()方法中

代理类完成的功能

  1. 调用目标方法:执行目标方法的功能
  2. 功能增强,在目标方法调用时,增加功能。
方法原型:

参数: 
Object proxy:jdk创建的代理对象,无需赋值。
Method method:目标类中的方法,jdk提供method对象的
Object[] args:目标类中方法的参数, jdk提供的。

public Object invoke(Object proxy, Method method, Object[] args)

InvocationHandler接口:

表示你的代理要干什么。
怎么用: 1.创建类实现接口InvocationHandler
2.重写invoke()方法, 把原来静态代理中代理类要完成的功能,写在这。

2)Method类:

表示方法的, 确切的说就是目标类中的方法。

作用:
通过Method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法的参数)
Object ret = method.invoke(service2, "李四");

说明: method.invoke()就是用来执行目标方法的,等同于静态代理中的
//向厂家发送订单,告诉厂家,我买了u盘,厂家发货
float price = factory.sell(amount); //厂家的价格。

3)Proxy类:

核心的对象,创建代理对象。之前创建对象都是 new 类的构造方法()
现在我们是使用Proxy类的方法,代替new的使用。

方法: 静态方法 newProxyInstance() 
作用是: 创建代理对象, 等同于静态代理中的TaoBao taoBao = new TaoBao();

参数:

  • ​ClassLoader loader​​​类加载器,负责向内存中加载对象的。 使用反射获取对象的​​ClassLoader​​ 类a , ​​a.getCalss().getClassLoader()​​, 目标对象的类加载器
  • ​Class<?>[] interfaces​​: 接口, 目标对象实现的接口,也是反射获取的。
  • ​InvocationHandler​​h : 我们自己写的,代理类要完成的功能。

返回值:就是代理对象

public static Object newProxyInstance(ClassLoader loader,   Class<?>[] interfaces,   InvocationHandler h)

实现动态代理的步骤:

  1. 创建接口,定义目标类要完成的功能
  2. 创建目标类实现接口
  3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
    1.调用目标方法
    2.增强功能

4.使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。

第一步

public interface UsbSell {
float sell(int amount);
}

第二步

public class UsbKingFactory implements UsbSell {
@Override
public float sell(int amount) {
System.out.println("目标类中,执行了sell目标方法");
return 85.02f;

}
}

我们写了接口类,定义了功能,写了代理类,实现了接口功能,按照以前的操作,现在就需要写一个真正的代理类,创建对象.

第三步:

创建了​​Invocationhandler​​实现类,在invoke()方法中完成代理类de对象

  • 调用目标的方法
  • 增强功能

public class MyHandle implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
}

代理类的实现方法上进行修改

//之前的代理类
public class TaoBao implements usbSell {
// 声明 商家代理的厂家具体是谁
private UsbKingFactory factory =new UsbKingFactory();

@Override
// 实现销售U盘功能
public float sell(int amount) {
// 向厂家发送订单,告诉厂家,我买了U盘,厂家发货
// 发送给工厂,我需要的订单,返回报价
float price = factory.sell(amount);
// 商家需要加价也就是代理要增加价格
price = price + 25;
//在目标类的方法调用后,你做的其他功能,都是增强的意思
System.out.println("淘宝再给你返回一个优惠券,或者红包");
// 增加的价格
return price;
}
}

调用目标的方法

//传入是谁的对象,就给谁创建代理
public MyHandle(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args){
Object res =null;
// 向厂家发送订单,告诉厂家,我买了U盘,厂家发货
// 发送给工厂,我需要的订单,返回报价
// float price = factory.sell(amount);
res = method.invoke(target,args); //待执行目标方法,执行后返回值

//增强的方法 res
}

第四步: 使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型

创建一个MainShop类.

public class MainShop {
public static void main(String[] args){
// 1.创建对象,使用Proxy
// 2.创建目标对象
UsbSell factory = new UsbKingFactory();
// 3.创建Invocationhandler对象
InvocationHandler myHandle = new MyHandle(factory);

// 4.创建代理对象
UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
myHandle);
// 通过代理执行方法
float price = proxy.sell(1);
System.out.println("通过动态代理对象,调用方法:" +price);
}
}

JDK动态代理执行流程

我们先复习一下,Proxy类,实现动态代理的流程,使用返回指定接口的代理类实例,

Java-JDK动态代理(AOP)_spring

我们此时debug一下程序,在invok实现类中打一个断点

Java-JDK动态代理(AOP)_java_02

此时我们再观察,代理对象MyHandler里面的invoke方法的参数

Java-JDK动态代理(AOP)_设计模式_03

Java-JDK动态代理(AOP)_java_04


举报

相关推荐

0 条评论