基于Java的设计模式 - 代理模式

2023-09-18 11:02:20

代理模式是一种使用代理对象来执行目标对象的方法并在代理对象中增强目标对象方法的一种设计模式。简单来讲就是在不修改目标对象的基础上,增强主业务逻辑的设计模式。

代理模式基本可分为三种

  • 静态代理
  • JDK动态代理
  • CGLIB动态代理

上述简单分就是静态和动态代理,静态代理即程序运行之前已创建了代理类,动态代理是程序运行时通过反射机制动态创建代理对象。

静态代理

DoService.java

//主业务接口
public interface DoService {
	void doSomething();
}

DoServiceImpl.java

public class DoServiceImpl implements DoService {

	@Override
	public void doSomething() {
		// TODO Auto-generated method stub
		System.out.println("业务操作");
	}

}

ServiceProxy.java

//代理类
public class ServiceProxy implements DoService {
	
	private DoService target;
	
	public ServiceProxy(){
		super();
		//创建目标对象
		target = new DoServiceImpl();
	}
	
	@Override
	public void doSomething() {
		// TODO Auto-generated method stub
		System.out.println("代理类--业务处理前操作");
		target.doSomething();
		System.out.println("代理类--业务处理后操作");
	}

}

TestStaticProxy.java

public class TestStaticProxy {
	public static void main(String[] args) {
		DoService service = new ServiceProxy();
		service.doSomething();
	}
}

JDK动态代理

DoService.java

//主业务接口
public interface DoService {
	void doSomething();
}

DoServiceImpl.java

public class DoServiceImpl implements DoService {

	@Override
	public void doSomething() {
		// TODO Auto-generated method stub
		System.out.println("业务操作");
	}

}

TestJdkProxy.java

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestJdkProxy {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		DoService target = new DoServiceImpl();
		// 使用JDK的Proxy动态代理,要求目标类必须实现接口
		// 因为其底层的执行原理,与静态代理相同
		DoService service = (DoService) Proxy.newProxyInstance(target.getClass().getClassLoader(), // 目标类的类加载器
			target.getClass().getInterfaces(), // 目标类所实现的所有接口
			new InvocationHandler() { // 匿名内部类

				// proxy:代理对象
				// method:目标方法
				// args 目标方法的参数列表
				@Override
				public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					// TODO Auto-generated method stub
					System.out.println("代理类--业务处理前操作");
					// 调用目标方法
					Object result = method.invoke(target, args);
					System.out.println("代理类--业务处理后操作");
					return result;
				}
			});
		service.doSomething();
	}
}

使用jdk的proxy实现代理,要求目标类与代理类实现相同的接口,若目标类不存在接口,则无法使用该方式实现

CGLIB动态代理

DoService.java

//主业务
public class DoService {
	public void doSomething() {
		System.out.println("业务操作");
	}
}

MyCglibFactory.java

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class MyCglibFactory implements MethodInterceptor {

	private DoService target;
	
	public MyCglibFactory() {
		super();
		// TODO Auto-generated constructor stub
		target = new DoService();
	}
	
	public DoService MyCglibCreator(){
		//创建增强器对象
		Enhancer enhancer = new Enhancer(); 
		//指定目标类,即父类
		enhancer.setSuperclass(DoService.class);
		//设置回调接口对象
		enhancer.setCallback(this);
		
		return (DoService) enhancer.create();
	}
	
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("代理类--业务处理前操作");
		Object result = method.invoke(target, args);
		System.out.println("代理类--业务处理后操作");
		return result;
	}

}

TestCglibProxy.java

public class TestCglibProxy {
	public static void main(String[] args) {
		DoService service = new MyCglibFactory().MyCglibCreator();
		service.doSomething();
	}
}

对于无接口的类,要为其创建动态代理,就要使用CGLIB来实现,CGLIB代理的生成原理是生成目标类的子类,而子类是增强过,这个子类对象就是代理对象,所以使用CGLIB生成动态代理,要求目标必须能够被继承,即不能是final的类

更多推荐

URL与URI小结

文章目录一、URL是什么?URL的一般形式:二、分类三、URI总结一、URL是什么?每条由Web服务器返回的内容都是和它管理的某个文件相关联的,这些文件中的每一个都有一个唯一的名字,叫做URL(通用资源定位符),是互联网上一种资源的地址。例如:http://www.google.com:80/index.htmlURL

实训笔记——Spark计算框架

实训笔记——Spark计算框架Spark计算框架一、Spark的概述二、Spark的特点三、Spark的安装部署(安装部署Spark的ClusterManager-资源调度管理器的)3.1本地安装--无资源管理器3.2Spark的自带独立调度器Standalone3.2.1主从架构的软件3.2.2Master/work

第26章_瑞萨MCU零基础入门系列教程之独立看门狗定时器-IWDT

本教程基于韦东山百问网出的DShanMCU-RA6M5开发板进行编写,需要的同学可以在这里获取:https://item.taobao.com/item.htm?id=728461040949配套资料获取:https://renesas-docs.100ask.net瑞萨MCU零基础入门系列教程汇总:https://b

在springboot下将mybatis升级为mybatis-plus

在springboot下将mybatis升级为mybatis-plus1.整体描述2.具体步骤2.1更新pom引用2.2更新yml配置2.3更新config配置2.4BaseEntity修改3.程序启动4.总结1.整体描述之前项目工程用的是mybatis,现在需要将其替换为mybatis-plus,mybatis-pl

电商项目高级篇-01 elasticsearch

电商项目高级篇-01elasticsearch1、linux下安装elasticsearch和可视化工具2、docker设置虚拟机开机启动和容器开机启动3、elasticsearch的curd3.1、新增、更新3.2、查询1、linux下安装elasticsearch和可视化工具将安装好jdk1.8和tomcat的ce

使用jmeter+ant+jenkins+git搭建自动化测试平台

最近正在学习自动化测试,于是随手搭建了一下jmeter+ant+jenkins+git平台。接下来,我会按照jdk,jmeter,ant,jenkins,git这个顺序一步一步的搭建起来。一、jdk。这个就不多说了。我用的是1.8版本的,配环境变量网上一大堆。二、jmeter。官网下载:ApacheJMeter-Dow

数据科学的文本技术 Text Technology(IR信息检索、搜索引擎)

一、文章摘要1.内容*IntroductiontoIRandtextprocessing,systemcomponents*Zipf,Heaps,andothertextlaws*Pre-processing:tokenization,normalisation,stemming,stopping.*Indexing:

在IntelliJ IDEA 中安装阿里P3C以及使用指南

在IntelliJIDEA中安装阿里P3C以及使用指南1.关于阿里p3c1.1说明1.2什么是P3C插件1.3p3c的作用是什么2如何在IDEA中安装p3c2.1插件安装2.2插件使用3.参考连接1.关于阿里p3c1.1说明代码规范检查插件P3C,是根据《阿里巴巴java开发手册(黄山版)》转化而成的自动化插件。1.2

Lnmp架构之mysql数据库实战1

1、mysql数据库编译编译成功2、mysql数据库初始化配置数据目录全局文件修改内容生成初始化密码并进行初始化设定3、mysql主从复制什么是mysql的主从复制?MySQL的主从复制是一种常见的数据库复制技术,用于将一个数据库服务器(称为主服务器)上的数据同步到另一个或多个数据库服务器(称为从服务器)上。在主从复制

ElasticSearch

文章目录一、引言1.1海量数据1.2全文检索二、ES概述2.1ES的介绍2.2ES的由来三、ElasticSearch安装3.1安装ES&Kibana3.2安装IK分词器四、ElasticSearch基本操作4.1ES的结构4.1.1索引Index,分片和备份4.1.2类型Type4.1.3文档Doc4.1.4属性Fi

【Linux学习笔记】 - 常用指令学习及其验证(下)

前言:本文延续上一篇文章【Linux学习笔记】-常用指令学习及其验证(上)对常用的指令进行介绍和验证。一、mv指令(1)功能:用来移动文件或者将文件改名(2)语法及验证:语法:mv[选项][源文件或目录][目标文件或目录]当第二个参数(即目标文件或目录)是不存在的文件或目录时,此时源文件或目录只能有一个,它将被重新命名

热文推荐