学习动态代理之前需要先搞清楚静态代理,可以回看我之前在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方法中完成代理类的功能
    1. 调用目标方法
    2. 增强功能
  • 使用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框架先行必备)相关推荐

  1. 一文带你搞懂从动态代理实现到Spring AOP

    摘要:本文主要讲了Spring Aop动态代理实现的两种方式. 1. Spring AOP Spring是一个轻型容器,Spring整个系列的最最核心的概念当属IoC.AOP.可见AOP是Spring ...

  2. proe常用c语言语句,带你轻松搞懂Proe条件语句

    原标题:带你轻松搞懂Proe条件语句 本文通过几个简单的例子介绍Proe中的条件语句,希望对你能有所帮助.Proe中使用的IF条件语句和C语言中的IF语句原理是一样的,其结构稍有差别.首先我们了解一下 ...

  3. 利用JDK动态代理机制实现简单拦截器

    利用JDK动态代理机制实现简单的多层拦截器 首先JDK动态代理是基于接口实现的,所以我们先定义一个接口 public interface Executer {public Object execute ...

  4. 深度剖析JDK动态代理机制

    摘要 相比于静态代理,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定一组接口及目标类对象就能动态的获得代理对象. 代理模式 使用代理模式必须要让代理类和目标类实现相同的接口,客户端通过 ...

  5. AOP 拦截器 JDK动态代理机制 struts2 mybatis spring-aop

    struts2拦截器兑现原理(转) struts2拦截器实现原理(转) 第一步:创建目标对象的接口 /** * 目标对象的接口 JDK的动态代理要求目标对象必须实现一个接口 *  * @author ...

  6. 一文带你轻松搞懂事务隔离级别(图文详解)

    本文由 SnailClimb 和读者 BugSpeak 共同完成. 事务隔离级别(图文详解) 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事务最经典也经常被拿出来说例子就是转账了 ...

  7. java 一个大事务下的新增、修改、查询_一文带你轻松搞懂事务隔离级别(图文详解)...

    点击上方"linkoffer", 选择关注公众号高薪职位第一时间送达 本文由 SnailClimb 和读者 BugSpeak 共同完成. 事务隔离级别(图文详解) 什么是事务? 事 ...

  8. JDK 动态代理与 CGLIB 动态代理,它俩真的不一样

    摘要:一文带你搞懂JDK 动态代理与 CGLIB 动态代理 本文分享自华为云社区<一文带你搞懂JDK 动态代理与 CGLIB 动态代理>,作者: Code皮皮虾 . 两者有何区别 1.Jd ...

  9. JDK动态代理学习笔记

    2019独角兽企业重金招聘Python工程师标准>>> 昨天被问了个问题,问题的大意是这样的:为什么 Proxy.newProxyInstance(ClassLoader loade ...

最新文章

  1. 计算机视觉系列最新论文(附简介)
  2. oracle阻塞查询,oracle 查询阻塞的sql语句
  3. vm虚拟机和windows共享文件夹
  4. 垃圾回收机制之标记清除算法
  5. websocket + node.js聊天系统
  6. stdout字符串过滤输出
  7. 手动启动_电站首台机组首次手动开机启动一次性成功
  8. [转]pip – pip安装和使用教程
  9. 使用截图工具FastStone Capture
  10. 大地高和正常高、正高的详细说明
  11. 【视频教程】帝国CMS制作网站系列教程08—单页模板的制作
  12. 在纽约寻找童真——新泽西州乐高乐园探索中心的美好一天
  13. 操作系统之文件管理(一)
  14. OpenCV极坐标转换函数warpPolar的使用
  15. 搭建基于企业微信的SCRM系统
  16. 几个主流的Java连接池
  17. java的万里长征之第一步
  18. sqlserver 高版本数据倒到低版本 不同SQL Server版本间的数据库恢复问题
  19. 数据治理之安装DSS和LINKIS,QUALITIS过程中遇到的问题汇总
  20. 需求、概要、详细设计怎么做,做那些?

热门文章

  1. Git恢复之前版本的两种方法reset、revert(图文详解)
  2. 基于土壤数据与机器学习算法的农作物推荐算法代码实现
  3. 百度,这下要歇菜了?
  4. Oracle Mybatis批量修改
  5. 【PMP】项目各阶段分别运用什么工具与技术汇总
  6. 一生中该听的100首外国歌曲,献给所有喜爱音乐的人!
  7. Shader 材质BlenningPhong 代码模块
  8. 墨墨背单词mysql_[英语] 何凯文考研英语第271句
  9. 10/13新生研讨课心得
  10. 11.网络编程的学习总结