• Java 代理模式


    代理模式分为静态代理和动态代理

    静态代理

    介绍

    类似于生活中的中介代理房东租房、婚介代理要结婚的情侣布置婚礼现场等等。

    实现

    拿房东租房为例

    Rent接口

    package com.curtian.study.static_proxy.demo1;
    
    public interface Rent {
    
        void rent();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Rent接口的第一个实现类,房东

    package com.curtian.study.static_proxy.demo1;
    
    /**
     * 房东
     */
    public class Host implements Rent{
    
        @Override
        public void rent() {
            System.out.println("房东租房子");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Rent接口的第二个实现类,中介

    package com.curtian.study.static_proxy.demo1;
    
    public class Proxy implements Rent{
    
        private Host host;
    
        @Override
        public void rent() {
            seeHouse();
            host.rent();
            hetong();
            rate();
        }
    
        public Proxy(Host host) {
            this.host = host;
        }
    
        private void seeHouse(){
            System.out.println("中介带看房子");
        }
    
        private void hetong(){
            System.out.println("签署租赁合同");
        }
    
        private void rate(){
            System.out.println("收取中介费");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    从代码中我们也可以发现,中介只是在被代理的类的方法上加了一些额外的方法(seeHouse、hetong、rate)

    静态代理总结

    接口(Rent租房接口)真实角色(Host房东)代理角色(Proxy房屋中介)组成。

    好处

    是可以是使真实角色操作更加存粹(房东只管租房一件事情),很明显的体现了面向对象七大原则的单一职责原则。公共业务就交给代理角色。

    缺点

    一个真实角色就对应一个代理角色,比如房东对应房屋中介、要结婚的情侣对应婚介所

    动态代理

    介绍

    拥有静态代理的所有优点以及可以动态生成代理类。

    分类

    动态代理分为三大类:

    • 基于接口的:jdk动态代理
    • 基于类的:cglib
    • java字节码实现的:javasist

    JDK动态代理

    (目前博主只了解了jdk动态代理)

    JDK动态代理核心

    Proxy类InvocationHandler接口
    Proxy用于生成代理类,实现InvocationHandler接口可以通过反射获取被代理的类的方法, 然后在此基础上添加一些附属操作

    举例

    给所有类的方法加一些日志。

    UserService接口
    package com.curtian.study.static_proxy.demo2;
    
    public interface Userservice {
    
        void add();
    
        void delete();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    UserServiceImpl类
    package com.curtian.study.static_proxy.demo2;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserServiceImpl implements Userservice{
        @Override
        public void add() {
            System.out.println("加法");
        }
    
        @Override
        public void delete() {
            System.out.println("减法");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    ProxyInvocationHandler(核心)
    package com.curtian.study.dynamic_proxy;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyInvocationHandler implements InvocationHandler {
    
        //被代理的对象
        private Object target;
    
        public void setTarget(Object target){
            this.target = target;
        }
    
        /**
         * 生成代理类
         * @return
         */
        public Object getProxy(){
            return Proxy.newProxyInstance(this.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(proxy.getClass().getName());
            log("调用了" + method.getName() + "方法");
            return method.invoke(target, args);
        }
    
        private void log(String msg){
            System.out.println(msg);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    Test(测试)
    /**
     * 动态代理
     * 介绍:动态代理和静态代理角色一样
     * 动态代理的代理类是动态生成的,不是我们直接写好的!
     * 动态代理分为两大类:基于接口的动态代理,基于类的动态代理。
     *      1.基于接口--Jdk动态代理【本次示例】
     *      2.基于类:cglib
     *      3.java字节码实现: javasist
     * 示例中的两个核心类/接口,Proxy类、invocationHandler接口
     *
     * */
    public class Main {
        public static void main(String[] args) {
            UserServiceImpl userService = new UserServiceImpl();
            ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
            proxyInvocationHandler.setTarget(userService);
            Userservice proxy = (Userservice) proxyInvocationHandler.getProxy();
            proxy.add();
            proxy.delete();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行情况:
    在这里插入图片描述

  • 相关阅读:
    css 实现虚线效果的3种方式详解
    使用pr的8大技巧 优漫动游
    c语言字符串函数下:strcmp、strncpy、strncat、strncmp、strstr、strtok、strerror
    操作系统:进程控制
    qt源码解析0--源码获取与调试环境准备
    优化资源利用率:kubernetes中装箱的好处与挑战
    网络安全(黑客技术)——自学思路
    前端的易错点
    Spring Boot 中自动装配机制的原理
    MySQL—MySQL的存储引擎之InnoDB
  • 原文地址:https://blog.csdn.net/qq_41953872/article/details/127719507