设为首页 加入收藏

TOP

9、Spring之代理模式(二)
2023-08-26 21:11:22 】 浏览:94
Tags:Spring
4.1、概念
  • 代理模式是二十三种设计模式中的一种,属于结构型模式

  • 它的思想就是在不改动目标方法代码的基础上,增强目标方法的功能

  • 它的实现就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用目标方法

  • 它的作用就是把不属于目标方法核心逻辑的代码从目标方法中剥离出来,从而实现解耦和统一维护

9.4.2、术语

  • 目标:封装了核心功能代码,的类、对象、方法

  • 代理:封装了增强功能代码、且能调用目标,的类、对象、方法

9.4.3、生活中的目标和代理

  • 广告商找大明星(目标)拍广告,需要经过经纪人(代理)

  • 买房者找卖房者(目标)购房,需要经过房产中介(代理)

9.5、静态代理

先将实现类CalculatorImpl还原为没有增加日志功能的状态,即9.2.1小节的状态

9.5.1、创建静态代理类CalculatorStaticProxy

image

注意:代理类和目标类要实现相同的接口,这样能保证它们有相同的方法列表

package org.rain.spring.proxy;

/**
 * @author liaojy
 * @date 2023/8/7 - 12:56
 */
public class CalculatorStaticProxy implements Calculator {

    // 将被代理的目标对象声明为成员变量
    private Calculator target;

    public CalculatorStaticProxy(Calculator target) {
        this.target = target;
    }

    public int add(int i, int j) {
        // 附加功能由代理类中的代理方法来实现
        System.out.println("[日志] add 方法开始了,参数是:" + i + "," + j);
        // 通过目标对象来实现核心业务逻辑
        int addResult = target.add(i, j);
        System.out.println("[日志] add 方法结束了,结果是:" + addResult);
        return addResult;
    }

    public int sub(int i, int j) {
        System.out.println("[日志] sub 方法开始了,参数是:" + i + "," + j);
        int subResult = target.sub(i, j);
        System.out.println("[日志] sub 方法结束了,结果是:" + subResult);
        return subResult;
    }

    public int mul(int i, int j) {
        System.out.println("[日志] mul 方法开始了,参数是:" + i + "," + j);
        int mulResult = target.mul(i, j);
        System.out.println("[日志] mul 方法结束了,结果是:" + mulResult);
        return mulResult;
    }

    public int div(int i, int j) {
        System.out.println("[日志] div 方法开始了,参数是:" + i + "," + j);
        int divResult = target.div(i, j);
        System.out.println("[日志] div 方法结束了,结果是:" + divResult);
        return divResult;
    }
}

9.5.2、测试

image

package org.rain.spring.test;

import org.junit.Test;
import org.rain.spring.proxy.CalculatorImpl;
import org.rain.spring.proxy.CalculatorStaticProxy;

/**
 * @author liaojy
 * @date 2023/8/7 - 14:12
 */
public class ProxyTest {

    @Test
    public void testStaticProxy(){
        CalculatorStaticProxy calculatorStaticProxy = new CalculatorStaticProxy(new CalculatorImpl());
        int addResult = calculatorStaticProxy.add(1, 2);
        System.out.println(addResult);
    }

}

9.5.3、静态代理的缺点

  • 静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性

  • 当其他目标类也需要附加日志,就得创建更多静态代理类,还是产生了大量重复的代码;而且日志功能还是分散的,没有统一管理

9.6、动态代理

动态代理的意思是,在代码运行的过程中动态地生成目标类的代理类

9.6.1、创建生成代理对象的工厂类ProxyFactory

image

比起实现固定接口方法的静态代理,动态代理的关键是能动态获取并实现目标的接口方法;
因此动态代理能对任意目标对象的核心业务方法(接口方法)进行增强

package org.rain.spring.proxy;

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

/**
 * @author liaojy
 * @date 2023/8/7 - 23:07
 */
//这个类不是一个代理类而是一个工具(工厂)类,用于动态生成目标对象的代理对象
public class ProxyFactory {

    //因为被代理的目标对象是任意的,所以目标对象变量的类型设为Object
    private Object target;

    //通过工厂类的有参构造方法,对目标对象变量进行赋值
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //生成任意目标对象所对应的代理对象;因为不确定动态生成的代理对象的类型,所以返回值设为Object
    public Object getPoxy(){

        //通过目标对象获取应用类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();

        //获取目标对象实现的所有接口的class对象所组成的数组
        Class<?>[] interfaces = target.getClass().getInterfaces();

        //通过InvocationHandler的匿名内部类,来设置代理类中如何重写接口中的抽象方法
        InvocationHandler invocationHandler = new InvocationHandler() {

            //通过
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java 中的 7 种重试机制,还有谁.. 下一篇切面实现下单请求防重提交功能(..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目