Spring日常笔记记录10--动态代理实现InvocationHandler
动态代理
动态代理是指,程序在整个运行构成中根本就不存在目标类的代理类,目标对象的代理对象只是由代理生成工具(不是真实定义的类)在程序运行时由JVM根据反射等机制动态生成的。代理对象与目标对象的代理关系在程序运行时才确立。
一、JDK动态代理
动态代理的实现方式常用的有两种:使用JDK的Proxy,与通过CGLIB生成代理。jdk的动态要求目标对象必须实现接口,这是Java设计上的要求。
从jdk1.3以来,Java语言通过java.lang.reflect包提供三个支持代理模式Proxy,Method和InvocationHandler。
二、CGLIB动态代理
第三方的工具库,创建代理对象,原理是继承。通过继承目标类,创建子类。
子类就是代理对象,要求目标类不能是final的,方法也不能是final的
三、JDK动态代理底层实现
反射包 java.lang.reflect , 里面有三个类 : InvocationHandler , Method, Proxy.
1)InvocationHandler 接口(调用处理器):就一个方法invoke()
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能就写在invoke()方法中。
代理类完成的功能:
1. 调用目标方法,执行目标方法的功能
2. 功能增强,在目标方法调用时,增加功能。
2)方法原型:
参数: Object proxy:jdk创建的代理对象,无需赋值。
Method method:目标类中的方法,jdk提供method对象的
Object[] args:目标类中方法的参数, jdk提供的。
public Object invoke(Object proxy, Method method, Object[] args)
1) 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();
三、JDK动态代理实现步骤:
1.创建目录类,SomeServiceImpl目标类,给它的doSome,doOther增加输出时间和事务。



2.创建InvocHandler接口的实现类,在这个类实现给目标方法增加功能。
package com.hlc.handler; import com.hlc.util.ServiceTools; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { //目标对象 private Object target; //SomeServiceImpl类 public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //通过代理对象执行时,会调用执行invoke() Object res = null; ServiceTools.doLog(); //执行目标类的方法,通过Method类实现 res = method.invoke(target,args); //SomeServiceImpl , doOther() , doSome() ServiceTools.doTrans(); //目标方法的执行结果 return res; } }
3.使用jdk中类Proxy,创建代理对象。实现创建对象的能力。
package com.hlc; import com.hlc.handler.MyInvocationHandler; import com.hlc.service.SomeService; import com.hlc.service.impl.SomeServiceImpl; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class MyApp { public static void main(String[] args) { //使用jdk的Proxy创建代理对象 //创建目标对象 SomeService target = new SomeServiceImpl(); //使用InvocationHandler对象 InvocationHandler handler = new MyInvocationHandler(target); //使用Proxy创建代理 SomeService proxy = (SomeService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(),handler ); //通过代理执行方法,会调用handler中的invoke() proxy.doSome(); } }
运行结果:
执行了MyInvocationHandler中的involved
非业务方法,方法的执行时间:Mon Jul 26 00:25:49 CST 2021
执行业务方法doSome
方法执行完毕后,提交事务
四、动态代理的作用
1.在目标类源代码不改变的情况下,增加功能
2.减少代码的重复
3.专注业务逻辑代码
4.解耦合,让业务功能和日志、事务和非事务功能分离
浙公网安备 33010602011771号