【设计模式】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,另一 ...
随机推荐
- Vscode个性化设置:让一个小萌妹陪你敲代码
前言 大家平时都用什么代码编辑器啊!我个人比较喜欢用vscode,因为有以下几点: 开源,免费: 自定义配置 集成git 智能提示强大 支持各种文件格式(html/jade/css/less/sass ...
- react native 0.6x 在创建项目时,CocoaPods 的依赖安装步骤卡解决方案
前言 你需要做两件事 gem换源 pod repo 换源 实战 如果你已经成功安装了CocoaPods.那么这里你需要卸载它.gem换源1. 卸载CocoaPods 查看gem安装的东西 gem li ...
- Vue引入vuetify框架你需要知道的几点
1.命令行安装 npm install vuetify --save 2.在src目录中创建一个名为的文件夹plugins在里面,添加一个vuetify.js文件.代码如下 import Vue fr ...
- 3. Caller 服务调用 - dapr
前言 上一篇我们讲了使用HttpClient的方式调用,那么如果我们现在需要更换为通过dapr实现服务调用,我们需要做哪些事情呢? Caller.Dapr 入门 如果我们的项目原本使用的是Caller ...
- arcgis创建postgre企业级数据库
什么是企业级地理数据库? 企业级地理数据库(ArcSD Enterprise,sde)是和 arcGIS 套件集成程度最高的地理数据库:创建时需要用到安装 arcGIS Server 时的 [ecp ...
- 入门Python数据分析最好的实战项目(一)分析篇
数据初探 首先导入要使用的科学计算包numpy,pandas,可视化matplotlib,seaborn,以及机器学习包sklearn. python学习交流群:660193417### import ...
- Unity3D学习笔记7——GPU实例化(2)
目录 1. 概述 2. 详论 2.1. 实现 2.2. 解析 3. 参考 1. 概述 在上一篇文章<Unity3D学习笔记6--GPU实例化(1)>详细介绍了Unity3d中GPU实例化的 ...
- Eclipse Ctrl+鼠标左键不能查看源代码
查询当前项目的使用的java包版本. 找到java包相应版本的安装路径. 在 "Source Attachment"对话框下,选择"External location&q ...
- VxWorks环境搭建与学习
搭建环境所需的所有资源: https://pan.baidu.com/s/1sUF2I_DBHs-86IUJ4Ykn2Q 提取码: t7sj 实时系统vxWorks - Shell命令 https:/ ...
- 如何做出一个好的c++游戏
目录 一.游戏分类 1.文字型 2.画图型 3.键盘型 二.游戏创意 你的程序可以比较激情.热血 1.打怪,爆装备型 2.答题闯关型 可以添加一些不可思议的物品和玩法 三.学号c++/c的语法,是成功 ...