带你轻松搞懂JDK动态代理机制(ssm框架先行必备)
学习动态代理之前需要先搞清楚静态代理,可以回看我之前在Mybatis里写的代理那一篇文章
MyBatis入门基础3 ---代理
动态代理
使用反射机制,在程序执行过程中,创建代理类对象,无需创建类文件,代理的目标类是活动的,可以设计的。
动态代理需要的三个类
需要使用反射包 java.lang. reflect里面有三个类:
InvocationHandler(接口):表示代理要干什么(功能增强)
Method:表示目标类的方法
Proxy:创建代理对象
InvocationHandler接口
InvocationHandler是一个接口,在这个接口中只有一个invoke()方法,我们将代理类要完成的功能写在invoke()中,我们来看一下invoke()方法
Object invoke(Object proxy,Method method,0bject[] args)
invoke有三个参数
proxy:jdk创建的代理对象,无需赋值
method:目标类中的方法,也是jdk提供的
0bject[] args:目标类中方法的参数,jdk提供的
用法:首先创建一个类实现InvocationHandler接口,然后重写invoke(),我们将代理要完成的功能写在invoke()中,代理要实现的功能有两个:1.调用目标方法,2,完成对目标方法的增强
Method类
通过method可以执行某个目标类的方法。
- method.invoke(目标对象,方法参数),这里的invoke和上述接口中的invoke碰巧同名而已。
Proxy类
我们通过调用Proxy里的静态方法newProxyInstance()创建代理对象,返回值就是代理对象
public static Obiect newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
newProxyInstance方法依然是有三个参数
ClassLoader loader:目标对象的类加载器,通过反射获取
Class[] interfaces:目标对象实现的接口,通过反射获取的
InvocationHandler h:我们自己写的代理类要完成的功能
实现动态代理的步骤:
- 创建接口,定义目标类要完成的功能
- 创建目标类实现接口
- 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
- 调用目标方法
- 增强功能
- 使用Proxy类的静态方法,创建代理对象。并把返回值转为接口类型。(目标类一定是继承接口的,所以代理类对象可以返回接口类型)
我们来演示一下,我们以卖U盘为例,先看结构
厂家为目标类:定义U盘初始价格。商家为代理,首先获取厂家的初始价格,然后增加价格,我们以商店为测试,查看我们的购买价格是多少。
先定义目标接口:service.UserSell 这里我们定义了此次测试的主要功能:sell方法
package DynamicProxy.service;/*** @author wangkx*/
public interface UsbSell {/*** sell 目标方法* @param amount* @return*/Integer sell(int amount);
}
定义目标类实现目标接口:factory.UsbFactory 厂家重写sell方法,定义出厂价为85元。
import DynamicProxy.service.UsbSell;/*** 目标类* @author wangkx*/
public class UsbFactory implements UsbSell {@Override/*** sell:目标方法* @param amount 数量*/public Integer sell(int amount) {System.out.println("目标类执行的sell目标方法");return 85;}
}
接下来实现带来要完成的功能:handler.SellHandler ---- 增加价格
package DynamicProxy.handler;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** @author wangkx* SellHandler必须实现InvocationHandler,将代理类要完成的功能写在invoke中* 1:调用目标方法;2:功能的增强*/
public class SellHandler implements InvocationHandler {private Object target = null;/*** 目标对象是活动的,传入谁,就给谁创建代理对象,我们用target来接收目标对象,构造方法给其赋值;* @param target*/public SellHandler(Object target) {//此时target就是目标对象this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object res = null;//proxy:目标对象;method:目标方法;args:目标方法的参数;//method.invoke(target,args); ----- 调用目标方法res = method.invoke(target,args);//增强功能 :就是加个价格,目标方法卖85,代理完之后卖95if(res != null){Integer price = (Integer)res;price += 10;res = price;}System.out.println("目标方法被增强了");return res;}
}
最后在商店中进行测试:MainShop
package DynamicProxy;import DynamicProxy.factory.UsbFactory;
import DynamicProxy.handler.SellHandler;
import DynamicProxy.service.UsbSell;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;/*** @author wangkx*/
public class MainShop {public static void main(String[] args) {//使用proxy创建代理对象//1.创建目标对象(多态)UsbSell factory = new UsbFactory();//2.创建InvocationHandler对象 -- 把factory传给SellHandler,相当于我们要给factory对象增强InvocationHandler handler = new SellHandler(factory);//3.创建代理对象,返回值是接口类型,目标对象实现了接口,所以可以转成接口类型UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces (),handler);//4.测试:通过代理对象执行方法System.out.println("动态代理增强后的价格是:"+proxy.sell(1));}
}
查看结果
我们发现,当我们以代理类调用sell方法时,目标方式执行了,代理增强的功能也执行了。
在静态代理中,一个代理类只能代理一个目标类,同时可能有多个代理类代理同一个目标类,当我们修改了目标类中的目标方法时,所有的代理类都会受到影响,需要重写目标方法。
而动态代理无需指定目标类,在上述案例中 实现代理增强功能时,我们以Object target来接收目标类。理论上我们可以接收无限多个目标类,当后续修改或是添加目标方法时,我们只需要在这里修改增强方法即可,减少了后期维护的成本。
带你轻松搞懂JDK动态代理机制(ssm框架先行必备)相关推荐
- 一文带你搞懂从动态代理实现到Spring AOP
摘要:本文主要讲了Spring Aop动态代理实现的两种方式. 1. Spring AOP Spring是一个轻型容器,Spring整个系列的最最核心的概念当属IoC.AOP.可见AOP是Spring ...
- proe常用c语言语句,带你轻松搞懂Proe条件语句
原标题:带你轻松搞懂Proe条件语句 本文通过几个简单的例子介绍Proe中的条件语句,希望对你能有所帮助.Proe中使用的IF条件语句和C语言中的IF语句原理是一样的,其结构稍有差别.首先我们了解一下 ...
- 利用JDK动态代理机制实现简单拦截器
利用JDK动态代理机制实现简单的多层拦截器 首先JDK动态代理是基于接口实现的,所以我们先定义一个接口 public interface Executer {public Object execute ...
- 深度剖析JDK动态代理机制
摘要 相比于静态代理,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定一组接口及目标类对象就能动态的获得代理对象. 代理模式 使用代理模式必须要让代理类和目标类实现相同的接口,客户端通过 ...
- AOP 拦截器 JDK动态代理机制 struts2 mybatis spring-aop
struts2拦截器兑现原理(转) struts2拦截器实现原理(转) 第一步:创建目标对象的接口 /** * 目标对象的接口 JDK的动态代理要求目标对象必须实现一个接口 * * @author ...
- 一文带你轻松搞懂事务隔离级别(图文详解)
本文由 SnailClimb 和读者 BugSpeak 共同完成. 事务隔离级别(图文详解) 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事务最经典也经常被拿出来说例子就是转账了 ...
- java 一个大事务下的新增、修改、查询_一文带你轻松搞懂事务隔离级别(图文详解)...
点击上方"linkoffer", 选择关注公众号高薪职位第一时间送达 本文由 SnailClimb 和读者 BugSpeak 共同完成. 事务隔离级别(图文详解) 什么是事务? 事 ...
- JDK 动态代理与 CGLIB 动态代理,它俩真的不一样
摘要:一文带你搞懂JDK 动态代理与 CGLIB 动态代理 本文分享自华为云社区<一文带你搞懂JDK 动态代理与 CGLIB 动态代理>,作者: Code皮皮虾 . 两者有何区别 1.Jd ...
- JDK动态代理学习笔记
2019独角兽企业重金招聘Python工程师标准>>> 昨天被问了个问题,问题的大意是这样的:为什么 Proxy.newProxyInstance(ClassLoader loade ...
最新文章
- 计算机视觉系列最新论文(附简介)
- oracle阻塞查询,oracle 查询阻塞的sql语句
- vm虚拟机和windows共享文件夹
- 垃圾回收机制之标记清除算法
- websocket + node.js聊天系统
- stdout字符串过滤输出
- 手动启动_电站首台机组首次手动开机启动一次性成功
- [转]pip – pip安装和使用教程
- 使用截图工具FastStone Capture
- 大地高和正常高、正高的详细说明
- 【视频教程】帝国CMS制作网站系列教程08—单页模板的制作
- 在纽约寻找童真——新泽西州乐高乐园探索中心的美好一天
- 操作系统之文件管理(一)
- OpenCV极坐标转换函数warpPolar的使用
- 搭建基于企业微信的SCRM系统
- 几个主流的Java连接池
- java的万里长征之第一步
- sqlserver 高版本数据倒到低版本 不同SQL Server版本间的数据库恢复问题
- 数据治理之安装DSS和LINKIS,QUALITIS过程中遇到的问题汇总
- 需求、概要、详细设计怎么做,做那些?