Java中的代理模式

news2024/9/22 19:30:15

Java中的代理模式

    • 1. 静态代理
    • JDK动态代理
    • CGLib动态代理

1. 静态代理

接口

public interface ICeo {

    void meeting(String name) throws InterruptedException;
}

目标类

public class Ceo implements ICeo{

    public void meeting(String name) throws InterruptedException {
        Thread.sleep(2000);
        System.out.println("和"+name+"谈成了34亿的项目");
    }
}

代理类

public class CeoProxy implements ICeo{

    private Ceo ceo;

    public CeoProxy(Ceo ceo) {
        this.ceo = ceo;
    }

    @Override
    public void meeting(String name) throws InterruptedException {

        System.out.println("秘书登记来访: "+name);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ceo.meeting(name);
        stopWatch.stop();
        double totalTimeMillis = stopWatch.getTotalTimeSeconds();
        System.out.println("耗时: "+totalTimeMillis);

    }
}

测试

public class CeoTest {

    public static void main(String[] args) throws InterruptedException {
        Ceo ceo = new Ceo();
        CeoProxy ceoProxy = new CeoProxy(ceo);
        ceoProxy.meeting("XXX");

    }
}

JDK动态代理

接口

public interface IDao {

    void select();
}

目标类

public class UserDao implements IDao{
    @Override
    public void select() {
        try {
            Thread.sleep(2000);
            System.out.println("select ----");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

动态代理类
在这里插入图片描述

public class JdkProxy implements InvocationHandler {

    private Object target;

    public JdkProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        StopWatch stopWatch = new StopWatch();
        System.out.println("前置方法");
        stopWatch.start();
        Object obj = method.invoke(target, args);
        stopWatch.stop();
        System.out.println("后置方法");
        System.out.println("耗时: "+stopWatch.getTotalTimeSeconds());
        return obj;
    }
}

测试

public class DaoTest {

    public static void main(String[] args) {
        UserDao userDao = new UserDao();
        IDao dao = (IDao) Proxy.newProxyInstance(UserDao.class.getClassLoader(), UserDao.class.getInterfaces(), new JdkProxy(new UserDao()));
        dao.select();
    }
}

总结:

  1. 动态生成代理类
  2. 通过实现接口生成代理类(目标接口必须实现接口)
  3. 代理类是实现接口的方式
  4. 调用目标类使用反射调用
  5. 目标类调用本类方法只会代理一次

CGLib动态代理

在这里插入图片描述

目标类

public class ZlmDao {

    public void select(){
        try {
            Thread.sleep(2000);
            System.out.println("select ---");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

代理类

public class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        System.out.println("前置增强");
        Object result = proxy.invokeSuper(obj, args);
        stopWatch.stop();
        System.out.println("后置增强");
        System.out.println("耗时: "+stopWatch.getTotalTimeSeconds());
        return result;
    }
}

测试

public class ZlmDaoTest {
    public static void main(String[] args) {
        //实例化增强器
        Enhancer enhancer = new Enhancer();
        //设置需要代理的目标类
        enhancer.setSuperclass(ZlmDao.class);
        //设置拦截对象回调的实现类
        enhancer.setCallback(new CglibProxy());
        //生成代理类
        ZlmDao zlmDao = (ZlmDao) enhancer.create();
        zlmDao.select();
    }
}

总结

  1. 通过ASM第三方框架动态代理
  2. 无需接口(final修饰的类和方法除外)
  3. 代理类通过继承目标类的方式实现代理
  4. 调用目标类,使用子类调用父类的方式直接调用
  5. invokeSuper目标类中调用本类方法会再次代理
  6. incoke目标类中调用本来方法只会调用一次

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/799191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

玩转回文:探索双下标法解谜,揭秘验证回文串的智慧攻略

本篇博客会讲解力扣“125. 验证回文串”的解题思路,这是题目链接。 验证回文串,我们最容易想到的思路就是,使用两个下标left和right,分别表示字符串的第一个字符和最后一个字符。接着,让两个下标不断向中间移动&#x…

Mysql 5.7 连接数爆满 清理连接数

Mysql 5.7 连接数爆满 清理连接数 我在做项目的时候遇到了这个报错,然后搜了半天也没有在网上找到mysql清理连接数的方案,后面还是自己写了一个 打开MySQL命令行或客户端,并使用管理员权限登录到MySQL服务器。 我这里使用的是navicat 输入…

智能小说文本字幕生成器

分享一个免费的,智能小说文本字幕生成器 智能分句。短词。 链接:https://pan.baidu.com/s/15xGlQg01LmbHHuGFZbgaiw?pwd0gjv 提取码:0gjv

动态代理的通用方法类

Java API给出的创建动态代理类中的两种方法(一般直接使用第二种方法): 生产代理对象的工厂类: package com.atguigu.pojo;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.refle…

【LeetCode-简单】剑指 Offer 06. 从尾到头打印链表(详解)

题目 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 题目地址:剑指 Offer 06. 从尾到头打印链表 - 力扣(LeetCode) 方法1:栈 思路 题目要求我们将链表的从尾到投打印一…

Backstaff InstallBuilder Crack

Backstaff InstallBuilder Crack 新的InstallBuilder调试器使安装程序开发过程中更容易识别和更正问题。它允许您在运行时查看和交互式编辑安装程序变量,提供逐步执行以测试安装程序的特定部分是否正常工作,允许从安装过程中的意外错误中恢复等等。Insta…

火车头神码ai伪原创【php源码】

大家好,小编来为大家解答以下问题,python中常用的类,python 类的用法,现在让我们一起来看看吧! 火车头采集ai伪原创插件截图:

《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(6)-Fiddler状态面板详解

1.简介 按照从上往下,从左往右的计划,今天就轮到介绍和分享Fiddler的状态面板了。 2.状态面板概览 Fiddler的状态面板概览,如下图所示: 3.状态面板详解 Fiddler底端状态栏面板详解,如下图所示: 如果你想…

网络安全工程师证书有什么用?什么是网络安全工程师?你想知道的都在这里

随着互联网的发展和大数据时代的到来,网络已经日渐深入到我们生活、工作中的方方面面,社会信息化和信息网络化,突破了应用信息在时间和空间上的障碍,使信息的价值不断提高。但是,与此同时,网页篡改、计算机…

解决容器内无法安装vim

用docker创建了一个容器,需要在容器内修改配置文件,突然发现vim竟然不能用,我直接一个apt-get install vim想解决的时候,发现竟然下载不了 看了网上一些文章发现还是源的问题: 从阿里云找到的源: deb htt…

25.1 Knife4j-Swagger的增强插件

1.Knife4j概述 Knife4j是一款基于Swagger UI的增强插件,它可以为Spring Boot项目生成美观且易于使用的API文档界面。它是Swagger UI的增强版,提供了更多的功能和定制选项,使API文档更加易读和易于理解。 2.Knife4j使用 Knife4j 集Swagger2…

常见面试题之常见技术场景

1. 单点登录这块怎么实现的? 1.1 概述 单点登录的英文名叫做:Single Sign On(简称 SSO ),只需要登录一次,就可以访问所有信任的应用系统。 在以前的时候,一般我们就单系统,所有的…

7.27 作业 QT

要求: 结果图: clock.pro: QT core gui QT texttospeechgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated …

No Spring环境Mybatis-Plus批量插入并返回主键的两种方式

批量插入,可以把Mybatis-Plus看作是Mybatis加强版;故Mybatis中的相关操作都可以在Mybatis-Plus中使用;在mysql数据库中支持批量插入,所以只要配置useGeneratedKeys和keyProperty就可以批量插入并返回主键了。 下面是批量插入的Dao层接口 一注解方式: 直接撸代码:…

面向对象编程:深入理解Java接口

文章目录 1. 接口:定义与生活中的类比2. 如何定义一个接口3. 接口中的成员4. 接口的实现4.1 单个接口的实现4.2 多个接口的实现 5. 多态与接口6. 新特性:默认方法与私有方法 接口在Java开发中扮演着重要的角色,它为类之间的交互定义了标准和规…

JDBC的的使用

首先导入jar包。 https://downloads.mysql.com/archives/c-j/ package com.test.sql;import java.sql.*;public class StudySql {public static void init() throws SQLException {Statement stmt null;Connection conn null;ResultSet res null;PreparedStatement pstm…

双点双向重发布实验

第一步配置IP地址 R1: [R1]int Serial 4/0/0 [R1-Serial4/0/0]ip address 12.0.0.1 24 [R1-Serial4/0/0]int g 0/0/0 [R1-GigabitEthernet0/0/0]ip address 14.0.0.1 24 [R1-GigabitEthernet0/0/0]int l0 [R1-LoopBack0]ip address 1.1.1.1 24 R2,R3,R4配置相同 第二步&#x…

一招教你用Java多线程写出死锁!!!

首先我们要知道什么是死锁: 1)进程死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁&am…

今天学学消息队列RocketMQ:消息类型

RocketMQ支持的消息类型有三种:普通消息、顺序消息、延时消息、事务消息。以下内容的代码部分都是基于rocketmq-spring-boot-starter做的。 普通消息 普通消息是一种无序消息,消息分布在各个MessageQueue当中,以保证效率为第一使命。这种消息…

一、Spring源码-ApplicationContext

Spring源码篇-ApplicationContext 一、ApplicationContext ApplicationContext到底是什么?字面含义是应用的上下文。这块我们需要看看ApplicationContext的具体的结构。 通过ApplicationContext实现的相关接口来分析,ApplicationContext接口在具备BeanF…