【设计模式】Java设计模式 - 动态代理
【设计模式】Java设计模式 - 动态代理
不断学习才是王道
继续踏上学习之路,学之分享笔记
总有一天我也能像各位大佬一样
一个有梦有戏的人 @怒放吧德德
最近工作比较忙,没啥时间学习
1、简介
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。动态代理就需要建立真实对象和代理对象关系,再去实现代理逻辑方法。
Java中实现动态代理有许多方法,JDK、CGLIB、Javassist、ASM,常用的是JDK和CGLIB,在spring中就是使用了这两种,然而mybatis还是用了Javassist。
2、JDK动态代理
提供简单的接口类以及其实现类,在通过建立真是对象与代理对象的关系,并且实现代理逻辑。
(1)、准备接口类
先提供接口类:
HelloWorldService:
package com.lyd.demo.service;
/**
* @Author: lyd
* @Description: 普通的接口
* @Date: 2022-08-17
*/
public interface HelloWorldService {
public void sayHelloWorld();
}
HelloWorldServiceImpl:
package com.lyd.demo.service.impl;
import com.lyd.demo.service.HelloWorldService;
/**
* @Author: lyd
* @Description: 接口实现类
* @Date: 2022-08-17
*/
public class HelloWorldServiceImpl implements HelloWorldService {
@Override
public void sayHelloWorld() {
System.out.println("Hello World!");
}
}
(2)、jdk动态代理
在JDK动态代理中,通过bind将真实对象和代理对象绑定起来,实现代理逻辑就要去实现java.lang.reflect.InvocationHandler接口,并且去实现invoke方法
①、首先需要声明 bind 方法去建立真实对象与代理对象的关系,把本类中的target保存真实对象。在通过Proxy的newProxyInstance方法来建立并生成对象,target.getClass().getClassLoader():target本身的类加载器,target.getClass().getInterfaces():把生成的动态代理对象下挂在接口中,this:当前对象,是定义实现方法逻辑的代理类。
②、实现InvocationHandler类中的invoke方法,可以实现代理逻辑,当我们使用了代理对象调度方法后就会进入到invoke方法中。
代码如下:
package com.lyd.demo.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author: lyd
* @Description: 动态代理绑定和代理逻辑实现
* @Date: 2022-08-17
*/
public class JdkProxyExample implements InvocationHandler {
// 真实对象
private Object target = null;
/**
* 建立代理对象和真实对象的代理关系,并且返回代理逻辑实现
* @param target 真实对象
* @return 代理对象
*/
public Object bind(Object target) {
this.target = target; // 绑定对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
/**
* 代理方法逻辑
* @param proxy 代理对象
* @param method 当前调度方法
* @param args 当前方法的参数
* @return 代理结果返回
* @throws Throwable 异常
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑方法");
System.out.println("在调度真实对象之前的服务");
Object obj = method.invoke(target, args); // 相当于调用了sayHelloWorld的方法
System.out.println("在调度真实对象之后的服务");
return obj;
}
}
(3)、实例
测试jdk动态代理
通过 HelloWorldService proxy = (HelloWorldService) jdkProxyExample.bind(new HelloWorldServiceImpl()); 去代理对象,然后就是使用proxy去点接口里面的方法了。
代码如下:
package com.lyd.demo.test;
import com.lyd.demo.jdk.JdkProxyExample;
import com.lyd.demo.service.HelloWorldService;
import com.lyd.demo.service.impl.HelloWorldServiceImpl;
/**
* @Author: lyd
* @Description: 测试jdk动态代理
* @Date: 2022-08-17
*/
public class jdkProxyText {
public static void main(String[] args) {
JdkProxyExample jdkProxyExample = new JdkProxyExample();
// 绑定关系,因为挂载带接口下,因此声明一个代理对象
HelloWorldService proxy = (HelloWorldService) jdkProxyExample.bind(new HelloWorldServiceImpl()); // 对象是new 实现类
// 调用方法
proxy.sayHelloWorld();
}
}
实验结果

可以带入参数:以下是带入参数的例子
在接口中的方法添加参数
public void sayHelloWorld(String name);
在实现类的实现方法中打印出来
System.out.println("Hello World! " + name);
调用方法的时候添加参数
// 调用方法
proxy.sayHelloWorld("lyd");
代理模式十分重要,要理解里面的逻辑,可以通过debug打断点去一步一步查看。
3、CGLIB 动态代理
JDK动态代理需要接口才能完成,而如果不提供接口,只有实现的方法类,可以使用三方插件CGLIB来动态代理,采用这个动态代理技术,需要引入三方jar包,可以搭建maven项目,引入CGLIB jar包 ,通过maven官网搜索添加,亦可以直接下载jar文件。
(1)、加入CGLIB依赖
maven引入依赖:
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
(2)、准备实现类
准备一个实现类,cglib不需要接口,只要实现就可以:
package com.lyd.demo.impl;
/**
* @Author: lyd
* @Description: 实现类
* @Date: 2022-08-17
*/
public class HelloWorldServiceImpl {
public void sayHelloWorld(String name) {
System.out.println("Hello World! " + name);
}
}
(3)、代理类
代理类需要MethodInterceptor去实现方法
这里使用了增强者enhancer,通过设置超类和使用setCallback方法设置代理类,CGLIB是通过invokeSuper方法代理逻辑的。
package com.lyd.demo.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Author: lyd
* @Description:
* @Date: 2022-08-17
*/
public class CglibProxyExample implements MethodInterceptor {
/**
* 生成CGLIB对象
* @param cls -----对象类
* @return Class的CGLIB代理对象
*/
public Object getProxy(Class cls) {
//CGLIB的增强类对象
Enhancer enhancer = new Enhancer();
//设置增强对象
enhancer.setSuperclass(cls);
//定义代理逻辑对象为当前对象,要求对象实现MethodInterceptor方法
enhancer.setCallback(this);
//生成返回代理对象
return enhancer.create();
}
/**
* 代理逻辑方法
* @param proxy 代理对象
* @param method 方法
* @param args 参数
* @param methodProxy 方法代理
* @return 代理逻辑返回
* @throws Throwable 异常处理
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("调用对象之前");
//使用CGLIB反射真实对象的方法
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("调用对象之后");
return result;
}
}
(4)、实例
测试:
package com.lyd.demo.test;
import com.lyd.demo.cglib.CglibProxyExample;
import com.lyd.demo.impl.HelloWorldServiceImpl;
/**
* @Author: lyd
* @Description: 测试CGLIB
* @Date: 2022-08-17
*/
public class CGLIBProxyTest {
public static void main(String[] args) {
CglibProxyExample cglibProxyExample = new CglibProxyExample();
HelloWorldServiceImpl proxy = (HelloWorldServiceImpl) cglibProxyExample.getProxy(HelloWorldServiceImpl.class); // 获取对象,可以不需要接口类
proxy.sayHelloWorld("lyd");
}
}
结果

【设计模式】Java设计模式 - 动态代理的更多相关文章
- java设计模式中的动态代理
Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...
- 设计模式之jdk动态代理模式、责任链模式-java实现
设计模式之JDK动态代理模式.责任链模式 需求场景 当我们的代码中的类随着业务量的增大而不断增大仿佛没有尽头时,我们可以考虑使用动态代理设计模式,代理类的代码量被固定下来,不会随着业务量的增大而增大. ...
- java中动态代理实现机制
前言: 代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系 ...
- [转载] java的动态代理机制详解
转载自http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代 ...
- java的动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- Java特性-动态代理
代理在开发中无处不在: 我们完成一个接口开发A,接口下有很多个实现类,这些类有些共同要处理的部分,比如每一个类都定义了接口A中的方法getXX(String name).我现在想把每次调用某个实现类的 ...
- java的动态代理机制
前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...
- java中动态代理
一.在java中怎样实现动态代理 1.我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象 接口: package org.dynamicproxy.test; public ...
- Java的动态代理机制详解(转)
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- (转)java的动态代理机制详解
原文出自:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一 ...
随机推荐
- 1.1 操作系统的第一个功能——虚拟化硬件资源 -《zobolの操作系统学习札记》
1.1 操作系统的第一个功能--虚拟化硬件资源 目录 1.1 操作系统的第一个功能--虚拟化硬件资源 问1:操作系统一般处于计算机系统的哪一个位置? 问2:管理硬件资源为什么要单独交给操作系统? 问3 ...
- 使用Vite2+TypeScript4+Vue3技术栈,如何入手开发项目
前言 今天,我们使用Vite2.0+Vue3+TS来试玩一下,开发一个demo项目.实战 我们,打开Vite官方网站(https://cn.vitejs.dev/). Vite (法语意为 " ...
- DAST 黑盒漏洞扫描器 第六篇:运营篇(终)
0X01 前言 转载请标明来源:https://www.cnblogs.com/huim/ 当项目功能逐渐成熟,同时需要实现的是运营流程和指标体系建设.需要工程化的功能逐渐少了,剩下的主要工作转变成持 ...
- 期末人福音——用Python写个自动批改作业系统
一.亮出效果 最近一些软件的搜题.智能批改类的功能要下线. 退1024步讲,要不要自己做一个自动批改的功能啊?万一哪天孩子要用呢! 昨晚我做了一个梦,梦见我实现了这个功能,如下图所示:功能简介:作对了 ...
- 正在运行中的docker容器设置自动重启
# demo : 你的容器名称 docker update –-restart=always demo
- 阿里云有奖体验:用PolarDB-X搭建一个高可用系统
体验简介 场景将提供一台配置了CentOS 8.5操作系统和安装部署PolarDB-X集群的ECS实例(云服务器).通过本教程的操作,带您体验如何使用PolarDB-X搭建一个高可用系统,通过直接ki ...
- Linux操作系统(7):rpm包管理和yum软件包在线管理
一.rpm 包的管理 介绍:一种用于互联网下载包的打包及安装工具,它包含在某些 Linux 分发版中.它生成具有.RPM 扩展名的文件.RPM 是 RedHat Package Manager(Red ...
- JAVA语言的跨平台性和JDK,JRE与JVM
Java虚拟机--JVM ~JVM:java虚拟机简称JVM是运行所有java程序的假想计算机,是java程序的运行环境,是java最具有吸引力的特性之一,我们编写的java代码,都运行在JVM之上 ...
- Solution -「CF1373G」Pawns
小清新线段树题(( 每个位置的边只能向靠右的三个方向走,最后要走到一条基准线上.即对于一个点 \((x, y)\),它最后应该落在 \((k, y + |k - x|)\). 士兵可以一个一个进行移动 ...
- python常用功能模块
路径相关:os.pathlib Windows注册表相关:winreg 系统cpu.内存.线程相关:psutil 文件.文件夹处理:shutil 解析和生成ini文件:ConfigParser:(co ...