Java代理

在软件开发中,代理模式是一种非常常见的设计模式。它允许我们通过一个代理对象间接访问目标对象,从而在不修改目标对象的情况下增强其功能。代理模式广泛应用于日志记录、权限校验、事务管理、延迟加载等场景。本文将带你深入了解Java中的代理模式,包括静态代理和动态代理的实现方式。

一、什么是代理

给目标对象提供一个代理对象,并且由代理对象控制着对目标对象的引用

在程序中,代理模式的核心思想是:

  • 代理对象:代替目标对象执行某些操作。

  • 目标对象:实际执行业务逻辑的对象。

  • 增强功能:在调用目标对象方法前后,代理对象可以添加额外的逻辑。

二、代理的目的

代理模式的主要目的是在不修改目标对象的情况下增强其功能。具体来说,代理模式可以实现以下目标:

1、控制访问:通过代理对象的方式间接的访问目标对象,防止直接访问目标对象给系统带来的不必要的复杂性

2、功能增强:通过代理业务对原有业务进行增强。

三、如何实现代理

Java中实现代理模式主要有两种方式:

  1. 静态代理,通过JDK实现

  2. 动态代理,通过JDK或者cglib实现

下面我们分别介绍这两种方式。

静态代理

在Java中,静态代理是一种设计模式,它通过创建一个代理类来间接访问目标类,从而在不修改目标类的情况下增强其功能。静态代理的核心思想是:手动编写代理类,代理类和目标类实现相同的接口,代理类持有目标类的引用,并在调用目标类方法的前后添加额外的逻辑。

Java代理_第1张图片

代码实例:

(1)目标类ClothesFactory

public class ClothesFactory implements ByClothes{

    public void clothes(String size){
        System.out.println("已经给您定制好了一件大小为"+size+"的衣服");
    }

    public void 机器处理(){

    }

    public void 原材料(){}
}

这是实际执行业务逻辑的类,它实现了 ByClothes 接口,并提供了 clothes 方法的具体实现。

(2)代理类Proxy 

public class Proxy implements ByClothes {

    private ClothesFactory clothesFactory = new ClothesFactory();


    @Override
    public void clothes(String size) {
        FrontService();
        clothesFactory.clothes(size);
        endService();
    }


    //前置服务
    public void FrontService() {
        System.out.println("根据您的需求进行市场调研");
    }

    //前置服务
    public void endService() {
        System.out.println("为您提供一条龙的包办服务");
    }


}

代理类也实现了 ByClothes 接口,它持有一个 ClothesFactory 的实例(目标类的引用),在调用目标类的 clothes 方法前后,代理类可以添加额外的逻辑(如 FrontService 和 endService)。

(3)接口ByClothes 

public interface ByClothes {
	public abstract  void clothes(String size);
}

这是一个接口,定义了 clothes 方法,目标类 ClothesFactory 和代理类 Proxy 都实现了这个接口。

 (4)客户端Test

public class Test {
	public static void main(String[] args){
		Proxy proxy =new Proxy();
		proxy.clothes("xxxl");
}
}

客户端通过代理类 Proxy 来调用 clothes 方法,客户端并不直接与目标类 ClothesFactory 交互,而是通过代理类间接访问。

静态代理的工作流程

  1. 客户端调用代理类的 clothes 方法。

  2. 代理类在调用目标类的 clothes 方法之前,执行前置逻辑(FrontService)。

  3. 代理类调用目标类的 clothes 方法,完成核心业务逻辑。

  4. 代理类在调用目标类的 clothes 方法之后,执行后置逻辑(endService)。

静态代理缺点:当目标类增多时,代理类直接增加代理的目标类,会造成代理关系混乱。

动态代理

动态代理是Java中一种更灵活的代理模式,动态代理的核心思想是:在运行时动态生成代理类,而不需要像静态代理那样为每个目标类手动编写代理类。

Java代理_第2张图片

代码实例:

(1)InvocationHandler接口的实现类DyProxy

package com.qcby;

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

public class DyProxy implements InvocationHandler {

    // 被代理的对象
    private Object o;

    // 构造方法,传入被代理的对象
    public DyProxy(Object o) {
        this.o = o;
    }

    // 获取代理对象
    public Object getProxyInterFace() {
        return Proxy.newProxyInstance(
            o.getClass().getClassLoader(), // 目标类的类加载器
            o.getClass().getInterfaces(), // 目标类实现的接口
            this // InvocationHandler 实例
        );
    }

    // 核心方法:代理逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        FrontService(); // 前置增强逻辑
        Object result = method.invoke(o, args); // 调用目标类的方法
        endService(); // 后置增强逻辑
        return result; // 返回方法执行结果
    }

    // 前置服务
    public void FrontService() {
        System.out.println("根据您的需求进行市场调研");
    }

    // 后置服务
    public void endService() {
        System.out.println("为您提供一条龙的包办服务");
    }
}

InvocationHandler这是一个接口,动态代理的核心逻辑通过实现它的 invoke 方法来定义。

DyProxy这是 InvocationHandler 的实现类,负责在运行时动态生成代理对象。

  • o:被代理的目标对象。
  • getProxyInterFace:通过 Proxy.newProxyInstance 方法生成代理对象。
  • invoke:在代理对象调用方法时,会执行 invoke 方法,在这里可以添加前置和后置逻辑。

(2)目标类ShootFactory

public class ShootFactory implements ByShoot {
    public void Shoot(String size) {
        System.out.println("已经为您定制好了一双大小为" + size + "的鞋子");
    }
}

目标类是实现特定接口的类,包含核心业务逻辑,动态代理可以代理任意实现了接口的目标类。 

 (3)接口ByShoot


public interface ByShoot {
    void Shoot(String size);
}

 动态代理要求目标类必须实现接口,因为 Proxy.newProxyInstance 需要接口信息来生成代理对象。

(4)客户端Test

public class Test {
    public static void main(String[] args) {
        ShootFactory shootFactory = new ShootFactory();
        ByShoot shoot = (ByShoot) new DyProxy(shootFactory).getProxyInterFace();
        shoot.Shoot("42");
    }
}

客户端通过 DyProxy 动态生成代理对象,并调用代理对象的方法,代理对象会在调用目标方法前后执行增强逻辑。

动态代理的工作流程

  1. 客户端调用 DyProxy 的 getProxyInterFace 方法,生成代理对象。

  2. 代理对象调用方法时,会触发 InvocationHandler 的 invoke 方法。

  3. 在 invoke 方法中:执行前置逻辑(FrontService),通过反射调用目标类的方法(method.invoke(o, args)),执行后置逻辑(endService)。

  4. 返回方法执行结果。

动态代理缺点:动态代理要求目标类必须实现接口,否则无法生成代理对象。

代理模式是Java中一种强大的设计模式,它通过代理对象间接访问目标对象,从而在不修改目标对象的情况下增强其功能。静态代理简单直观,但不够灵活;动态代理灵活性强,但必须依赖接口。在实际开发中,我们可以根据具体需求选择合适的代理方式。 

你可能感兴趣的:(java,开发语言)