【设计模式】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,另一 ...
随机推荐
- 南京大学 静态软件分析(static program analyzes)-- introduction 学习笔记
一.Programming Languages体系 静态程序分析是编程语言中应用层面下的一个细分领域,它是一个非常重要的核心内容. 在理论部分,考虑的是如何设计一个语言的语法和语义,如何设计语言的类型 ...
- Docker-配置华为云加速
到网址点击立即使用 https://www.huaweicloud.com/intl/zh-cn/product/swr.html 登录后进入镜像服务 按要求操作即可 相关命令 vi /etc/doc ...
- Xshell缺失mfc110u.dll文件解决方案(有下载链接)
解决方案 把下面两个文件都下载安装就可以了. 1.vcredist_x86.exe链接: https://pan.baidu.com/s/1njbNHdjqH6x34GQvj4BTBg提取码: pwq ...
- DAST 黑盒漏洞扫描器 第六篇:运营篇(终)
0X01 前言 转载请标明来源:https://www.cnblogs.com/huim/ 当项目功能逐渐成熟,同时需要实现的是运营流程和指标体系建设.需要工程化的功能逐渐少了,剩下的主要工作转变成持 ...
- rhel安装vmtools
第一步,vmware登录虚拟机,菜单栏找到"虚拟机"--"安装TOOLS" //如果打开虚拟机的光驱后没有文件.那么重复以上操作. 第二步,拷贝压缩文件到桌面: ...
- 说什么也要脱单——Python WEB开发:用Tornado框架制作简易【表白墙】网站
先来哔哔两句:(https://jq.qq.com/?_wv=1027&k=QgGWqAVF) 今天我们要用Python做Web开发,做一个简单的[表白墙]网站.众所周知表白墙的功能普遍更多的 ...
- Nacos配置失败(java.lang.IllegalStateException: failed to req API:/nacos/v1/ns/instance after all server)
解决: nacos服务器过载,可以删掉nacos文件夹下的data文件夹,重新启动.
- 基于Python+Sqlite3实现最简单的CRUD
一.基本描述 使用Python,熟悉sqlite3的基本操作(查插删改),以及基本数据类型.事务(ACID). 准备工作:在sqlite3的官网上下载预编译的sqlite文件(windows) ...
- 静态同步方法和解决线程安全问题_Lock锁
静态的同步方法锁对象是谁?不能是thisthis是创建对象之后产生的,静态方法优先于对象静态方法的锁对象是本类的cLass属性-->class文件对象(反射) 卖票案例出现了线程安全问题 卖出了 ...
- DENIED Redis is running in protected mode because protected mode is enabled
DENIED Redis is running in protected mode because protected mode is enabled redisson连接错误 Unable to i ...