Java JDK 动态代理实现和代码分析
JDK 动态代理
- 内容
- 一、动态代理解析
- 1. 代理模式
- 2. 为什么要使用动态代理
- 3. JDK 动态代理简单结构图
- 4. JDK 动态代理实现步骤
- 5. JDK 动态代理 API
- 5.1 java.lang.reflect.Proxy
- 5.1 java.lang.reflect.InvocationHandler
- 二、JDK 动态代理的实现(代码)
- 1. 项目结构图
- 2. IRentService 接口
- 3. LandlordServiceImpl 真实类
- 4. TransactionInvocationHandler 代理类
- 5. MyTransactionManager 增强类(模拟一下事务)
- 6. applicationContext.xml
- 7. TransactionInvocationHandlerTest 测试类
- 总结
参考博文:https://blog.csdn.net/jiankunking/article/details/52143504
内容
一、动态代理解析
1. 代理模式
Java 这门语言有许多种设计模式,其中一种设计模式为代理模式,所谓代理模式,就是通过代理方来操作目标对象,而不是自己直接调用。代理模式又分为静态代理和动态代理。
静态代理:针对每个被代理对象写一个代理类,当有多个代理对象时需要写多个代理类,操作不够优雅;
动态代理:可以根据接口动态的生成代理类,这动态生成的类不需要自己书写,jdk帮我们完成了,代码变得简洁。
无论是动态代理还是静态代理,最终都会产生一个代理类(class文件),里面都含有对被代理对象的封装,只是诞生的途径不一样。下面我主要介绍 JDK 动态代理 的实现和原理。
2. 为什么要使用动态代理
动态代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
3. JDK 动态代理简单结构图
4. JDK 动态代理实现步骤
- 创建一个实现接口InvocationHandler的类,它必须实现invoke方法
- 创建被代理的类以及接口
- 通过Proxy的静态方法 newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理
- 通过代理调用方法
注意: 真实类(被代理的类)必须实现接口
5. JDK 动态代理 API
5.1 java.lang.reflect.Proxy
Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
主要方法: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler hanlder)
- 方法职责:
为指定类加载器、一组接口及调用处理器生成动态代理类实例。 - 方法参数:
loader : 类加载器,一般传递真实对象的类加载器;
interfaces: 代理类需要实现的接口;
handler: 代理执行处理器,说人话就是生成代理对象帮你要做什么。 - 方法返回: 创建的代理对象。
5.1 java.lang.reflect.InvocationHandler
主要方法:public Object invoke(Object proxy, Method method, Object[] args)。
- 方法职责:
代理类实现该接口,负责集中处理动态代理类上的所有方法调用,让使用者自定义做什么事情, 对原来方法增强(加什么功能)。 - 方法参数:
proxy : 生成的代理对象;
method: 当前调用的真实方法对象;
args : 当前调用方法的实参。 - 方法返回: 真实方法的返回结果。
二、JDK 动态代理的实现(代码)
1. 项目结构图
2. IRentService 接口
package com.yy.homework.service;
public interface IRentService {void rent();
}
3. LandlordServiceImpl 真实类
package com.yy.homework.service.impl;
import com.yy.homework.service.IRentService;
public class LandlordServiceImpl implements IRentService {@Overridepublic void rent() {System.out.println("我是房东,我以1000一个月的房价给中介帮我出租!");}
}
4. TransactionInvocationHandler 代理类
package com.yy.homework.service.impl;import com.yy.homework.tx.MyTransactionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class TransactionInvocationHandler implements InvocationHandler {private Object target;@Autowiredprivate MyTransactionManager myTransactionManager;public Object getTarget() {return target;}public void setTarget(Object target) {this.target = target;}/*** @author YanYang* @description: 负责集中处理动态代理类上的所有方法调用,让使用者自定义做什么事情,对原来方法增强(模拟一下事务)* proxy:生成的代理对象* method:调用真实对象的方法* args:当前调用方法的实参* return:返回真实方法的返回结果*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object retVal = null;try {// 开启事务myTransactionManager.begin();// 调用真实对象的方法retVal = method.invoke(target, args);// 提交事务myTransactionManager.commit();} catch (Exception e) {// 回滚事务myTransactionManager.rollback();e.printStackTrace();}return retVal;}
}
5. MyTransactionManager 增强类(模拟一下事务)
package com.yy.homework.tx;import org.springframework.stereotype.Component;/*** @program: static-proxy* @ClassName MyTransactionManager* @description:* @author: YanYang**/
@Component
public class MyTransactionManager {public void begin() {System.out.println("开启事务");}public void commit() {System.out.println("提交事务");}public void rollback() {System.out.println("回滚事务");}
}
6. applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.yy.homework"/><bean id="transactionInvocationHandler" class="com.yy.homework.service.impl.TransactionInvocationHandler"><property name="target"><!-- 把房东真实对象参起来藏起来 --><bean class="com.yy.homework.service.impl.LandlordServiceImpl"/></property></bean></beans>
7. TransactionInvocationHandlerTest 测试类
package com.yy.homework.service.impl;import com.yy.homework.service.IRentService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.lang.reflect.Proxy;
import java.util.Arrays;/*** @program: static-proxy* @ClassName TransactionInvocationHandlerTest* @description:* @author: YanYang**/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TransactionInvocationHandlerTest {@AutowiredTransactionInvocationHandler handler;@Testpublic void invoke() {// 动态生成代理类并创建对象IRentService proxy = (IRentService) Proxy.newProxyInstance(// 类加载器,一般传递真实对象的类加载器handler.getTarget().getClass().getClassLoader(),// 代理类需要实现的接口,获取真实类实现的接口,生成代理类也是实现什么接口handler.getTarget().getClass().getInterfaces(),// 代理执行处理器,也就是生成代理对象帮你要做什么// 通过这个参数告诉 API 生成代理对象具体做什么handler);proxy.rent();System.out.println("handler = " + Arrays.toString(handler.getTarget().getClass().getInterfaces()));System.out.println("classLoader = " + handler.getTarget().getClass().getClassLoader());System.out.println("handler = " + handler);}
}
运行结果:
"C:\Program Files\Java\jdk-11.0.9\bin\java.exe"
com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.yy.homework.service.impl.TransactionInvocationHandlerTest,invoke
开启事务
我是房东,我以1000一个月的房价给中介帮我出租!
提交事务
handler = [interface com.yy.homework.service.IRentService]
classLoader = jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
handler = com.yy.homework.service.impl.TransactionInvocationHandler@36328d33Process finished with exit code 0
总结
以上就是对 JDK 动态代理 的总结了,代码仅供参考,欢迎讨论交流。
Java JDK 动态代理实现和代码分析相关推荐
- Java - JDK动态代理原理
Java - JDK动态代理原理 前言 一. JDK动态代理源码分析 1.1 生成目标代理类 getProxyClass0 1.1.1 KeyFactory 生成接口的虚引用 1.1.2 ProxyC ...
- java jdk动态代理学习记录
转载自: https://www.jianshu.com/p/3616c70cb37b JDK自带的动态代理主要是指,实现了InvocationHandler接口的类,会继承一个invoke方法,通过 ...
- Jdk动态代理 底层源码分析
前言 java动态代理主要有2种,Jdk动态代理.Cglib动态代理,本文主要讲解Jdk动态代理的使用.运行机制.以及源码分析.当spring没有手动开启Cglib动态代理,即:<aop:asp ...
- JDK动态代理实现与原理分析
1.何为代理 代理在我们的日常生活中,就有很多体现,房屋租赁代理,校园辅导班招生代理,化妆产品销售代理等.为什么我们要找代理呢,代理是专业的,是方便的.例如我们买一件化妆品,或买一本书,肯定是不能去找 ...
- java jdk动态代理 cglib动态代理demo
最近在研究java动态代理这块,以前也看了很多次java动态代理,感觉一直不是怎么明白,这两天看了看又明白了些,现给出我参考网上写的一个demo jdk动态代理实现: View Code import ...
- Java JDK 动态代理
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代 ...
- JDK动态代理实现原理详解(源码分析)
无论是静态代理,还是Cglib动态代理,都比较容易理解,本文就通过进入源码的方式来看看JDK动态代理的实现原理进行分析 要了解动态代理的可以参考另一篇文章,有详细介绍,这里仅仅对JDK动态代理做源码分 ...
- Java 结合实例学会使用 静态代理、JDK动态代理、CGLIB动态代理
前言 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 代理 很多人至今都是看到 代理就懵, 静态代理.动态代理.JDK动态代理.CGL ...
- 谁与争锋,JDK动态代理大战CGLib动态代理
文章目录 一.前言 二.基本概念 三.JDK 和 CGLib动态代理区别 3.1 JDK动态代理具体实现原理 3.2 CGLib动态代理 3.3 两者对比 3.4 使用注意 四.JDK 和 CGLib ...
最新文章
- CRM:把 isv.config.xml 按钮事件移动到 entity.onload()
- nginx编译安装,nginx静态资源访问和负载均衡的使用!
- Redis的搭建和Redis的集群搭建
- SOFAMosn 无损重启/升级
- 一句话讲清楚IOC容器以及什么时候使用@Autowired
- imagecomposition工程分析
- Ansys节点数据批量一键导出脚本生成CSV (ansys数据导出利用matlab脚本)
- 济南python工资一般多少-济南Python+人工智能
- linux免密码登录失败,ssh 免密码登录失败
- 视频直播CDN系统架构简析
- 运营商iptv服务器,IPTV 服务器
- sprintf函数的使用方法
- 芯片设计流程介绍(从硬件设计语言到芯片制造)
- Lipschitz continuity (利普希茨连续)
- 中文简体与繁体的转换
- 局域网内2台ubuntu电脑共享鼠标键盘
- 如何实现一个转动的太极图
- 填补空缺——压缩感知
- 李大潜:学习数学是战略性投资【导图版】
- 自动驾驶-第10届蓝桥杯Scratch省赛真题第5题