设计模式之代理模式

这篇具有很好参考价值的文章主要介绍了设计模式之代理模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

1:介绍

1.1:什么时候使用代理模式

当我们有对象因为安全性,不能直接对外暴露,或者是需要对对象的操作本身记录日志等信息时就可以考虑使用代理模式,

1.2:UML类图

享元设计模式,包含如下元素:

1:被代理类
    需要被代理的类
2:代理类
    代理类
3:客户端类
    使用代理类执行操作的类

UML图如下:

另外,代理又分为静态代理和动态代理,静态代理就是在编译器已经确定的代理方式,即是硬编码到程序中的,这种方式不灵活,动态代理是在运行期动态确定的代理方式,灵活度高。动态代理主要有jdk动态代理(需要有接口),asm,cglib(基于asm,简化操作)。来看下。

2:实例

源码 。

2.1:场景

数据库操作场景,需要在service方法调用前开启事务,方法调用后提交事务。

2.2:静态代理

  • 定义PersonService接口
public interface PersonService {
	public void savePerson();
}
  • 定义PersonServiceImpl
public class PersonServiceImpl implements PersonService {
	@Override
	public void savePerson() {
		System.out.println("保存人了");
	}
}
  • 定义事务类
public class Transaction {
	public void beginTransaction(){
		System.out.println("开启事务 ");
	}
	public void commit(){
		System.out.println("提交事务");
	}
}
  • 定义代理类
public class PersonServiceProxy implements PersonService {
	
	//目标类
	private PersonService personService;
	
	//增强类
	private Transaction transaction;
	
	//利用构造函数将目标类和增强类注入
	public PersonServiceProxy(PersonService personService,Transaction transaction) {
		this.personService = personService;
		this.transaction = transaction;
	}
	
	@Override
	public void savePerson() {
		// 这是每个类都需要的操作
		transaction.beginTransaction();

		personService.savePerson();

		// 这是每个类都需要的操作
		transaction.commit();
	}
}
  • 测试
@Test
public void serviceStatic() {
    new PersonServiceProxy(new PersonServiceImpl(), new Transaction()).savePerson();
}

开启事务 
保存人了
提交事务

假定我们现在又有个AnimalService如下:

public interface AnimalService {
	public void saveAnimal();
}

public class AnimalServiceImpl implements AnimalService {
    @Override
    public void saveAnimal() {
        System.out.println("保存动物了");
    }
}

则需要重新定义一个AnimalService的代理类来为其添加事务,如下:

public class AnimalServiceProxy implements AnimalService {

	//目标类
	private AnimalService animalService;

	//增强类
	private Transaction transaction;

	//利用构造函数将目标类和增强类注入
	public AnimalServiceProxy(AnimalService animalService, Transaction transaction) {
		this.animalService = animalService;
		this.transaction = transaction;
	}
	
	@Override
	public void saveAnimal() {
		// 这是每个类都需要的操作(PersonService写过一遍了,这里又要再写一遍,好痛苦!!!)
		transaction.beginTransaction();
		animalService.saveAnimal();
		// 这是每个类都需要的操作(PersonService写过一遍了,这里又要再写一遍,好痛苦!!!)
		transaction.commit();
	}
}

测试:

new AnimalServiceProxy(new AnimalServiceImpl(), new Transaction()).saveAnimal();

开启事务 
保存动物了
提交事务

如果我们有100个service,则同样的定义对应代理类的工作就要做100次,岂不疯了!!!但是,幸好我们有动态代理,接下来看下使用动态代理解决这个需要重复定义代理类的问题。

2.2:jdk动态代理

  • 定义InvocationHandler
public class ServiceInvocationHandler implements InvocationHandler {
    // 被代理的对象
    private Object target;
    private Transaction transaction;
    public ServiceInvocationHandler(Object obj){
        this.target=obj;
        this.transaction = new Transaction();
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 使用静态代理重复的事务开启操作就移动到这里了(只需要定义一次)
        this.transaction.beginTransaction();
        method.invoke(this.target, args);
        // 使用静态代理重复的事务提交操作就移动到这里了(只需要定义一次)
        this.transaction.commit();
        return null;
    }
}
  • 测试代理PersonService
@Test
public void serviceJdkProxy() {
    ((PersonService) ServiceProxyFactory.makeProxy(new PersonServiceImpl())).savePerson();
}

开启事务 
保存人了
提交事务

如果是增加了AnimalService只需要增加如下代码即可获取代理类:

((AnimalService) ServiceProxyFactory.makeProxy(new AnimalServiceImpl())).saveAnimal();

开启事务 
保存动物了
提交事务

但是,jdk动态代理有一个缺点就是必须要有接口,这在一定程度上限制了灵活度,如果是我们么有接口的话,则可以考虑使用cjlib来生成动态代理,一起看下!

2.3:cglib动态代理

  • 定义MethodInterceptor子类
public class ServiceMethodInterceptor implements MethodInterceptor {
    private Transaction transaction = new Transaction();
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // 开启事务(只需要写一次)
        transaction.beginTransaction();
        methodProxy.invokeSuper(o, objects);
        // 提交事务(只需要写一次)
        transaction.commit();
        return null;
    }
}
  • 获取代理工厂类
public class CjlibProxyFactory {
    public static Object getGcLibDynProxy(Object target){
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new ServiceMethodInterceptor());
        Object targetProxy= enhancer.create();
        return targetProxy;
    }
}
  • 测试
@Test
public void serviceCjlibProxy() {
    ((PersonServiceImpl) CjlibProxyFactory.getGcLibDynProxy(new PersonServiceImpl())).savePerson();
}

开启事务 
保存人了
提交事务

如果是增加了AnimalService则增加如下代码即可获取代理类:

((AnimalServiceImpl) CjlibProxyFactory.getGcLibDynProxy(new AnimalServiceImpl())).saveAnimal();

开启事务 
保存动物了
提交事务

写在后面

参考文章列表

java都有哪些动态代理机制? 。

Java中的代理模式——静态代理以及分析静态代理的缺点 。文章来源地址https://www.toymoban.com/news/detail-589864.html

到了这里,关于设计模式之代理模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式(5)代理模式

    一、介绍: 1、组成结构: (1)Subject/抽象角色:定义了RealSubject和Proxy的共用接口,这样就可以在任何使用        RealSubject的地方都可以使用Proxy (2)RealSubject/真实角色:定义Proxy所代表的真实实体 (3)Proxy/代理角色:保存一个引用使得代理可以访问实体,并提供一个与

    2024年02月13日
    浏览(39)
  • 【设计模式】代理模式

    5.1.1 概述 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。 Java中的代理按照代理类生成时机不同又分为静态代理和动态代理。静态代理代理类在编译期就生成

    2024年02月15日
    浏览(49)
  • 设计模式 -- 代理模式

    月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂) 央是一片海洋,海乃百川,代表着一块海绵(吸纳万物) 泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出) 月央泽,学习的一种过程,从白纸-吸收各种知识-不断输入输出变成自己的内容 希望大家一起坚持这个过程,也同样希望大家

    2023年04月08日
    浏览(39)
  • 设计模式二:代理模式

    1、什么是动态代理 可能很多小伙伴首次接触动态代理这个名词的时候,或者是在面试过程中被问到动态代理的时候,不能很好的描述出来,动态代理到底是个什么高大上的技术。不方,其实动态代理的使用非常广泛,例如我们平常使用的 Spring 中的 @Transactional 注解,其依赖

    2024年02月20日
    浏览(46)
  • 设计模式--代理模式

    笔记来源:尚硅谷Java设计模式(图解+框架源码剖析) 1)代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即 通过代理对象访问目标对象 2)这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能 3)被代理的对象可以

    2024年02月10日
    浏览(35)
  • 设计模式——代理模式

    代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一个代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以添加额外的功能或限制对目标对象的直接访问。 抽象主题(Subject Interface): 定义了目标对象和代理对象共有的接口。

    2024年01月17日
    浏览(49)
  • 设计模式-代理模式

    ● 为对象提供一个代理类,增强该对象的方法,控制对这个对象的访问 ● 静态代理和动态代理:静态代理就是编译的时候就已经确定,而动态代理就是运行时才会生成 缓存代理 ● 提供数据的缓存功能,避免数据库重复查询 实践 定义数据查询的接口 接口实现类实现接口

    2024年02月11日
    浏览(35)
  • 设计模式|代理模式

    ​代理模式指为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一个对象若不能直接引用另一个对象,而代理对象可以在客户端与目标对象之间起到中介的作用。 普通代理 普通代理模式是指在代理模式中,代理对象和真实对象都实现了相同的接口或继承

    2024年02月04日
    浏览(32)
  • 【设计模式】-代理模式

    在软件开发中,经常遇到需要对某个对象进行控制或者监控的场景。而直接修改对象的代码可能使代码变得复杂且难以维护。这时,使用代理模式(Proxy Pattern)可以很好地解决这个问题。          代理模式是一种结构型设计模式, 通过引入一个代理对象来替代原始对象

    2024年02月13日
    浏览(35)
  • 设计模式详解-代理模式

    类型:结构型模式 实现原理:创建具有现有对象的对象 作用:为其他对象提供一种代理以控制对这个对象的访问。 解决的问题:由于对象的访问条件不一,直接访问对象会造成麻烦问题 解决问题的方法:增加中间层。 何时使用:想在访问一个类时做一些控制。 实现核心:

    2024年02月12日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包