跳转至

代理(Proxy)🔥#

约 344 个字 25 行代码 1 张图片 预计阅读时间 8 分钟

意图#

为目标对象提供一种代理以控制对这个对象的访问。

结构#

代理模式结构
  • 服务接口(Service Interface)声明了服务接口。代理必须遵循该接口才能伪装成服务对象。
  • 服务(Service)类提供了一些实用的业务逻辑。
  • 代理(Proxy)类包含一个指向服务对象的引用成员变量。代理完成其任务(例如延迟初始化、记录日志、访问控制和缓存等)后会将请求传递给服务对象。下,代理会对其服务对象的整个生命周期进行管理。
  • 客户端(Client) 能通过同一接口与服务或代理进行交互,所以你可在一切需要服务对象的代码中使用代理。

静态代理#

代码实现#

服务接口:

Java
package com.luguosong.structural.proxy.static_proxy;

/**
 * @author luguosong
 */
public interface UserService {
    void addUser();

    void editUser();

    void deleteUser();
}

服务具体实现:

Java
package com.luguosong.structural.proxy.static_proxy;

/**
 * @author luguosong
 */
public class UserServiceImpl implements UserService{
    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void editUser() {
        System.out.println("修改用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

静态代理:

Java
package com.luguosong.structural.proxy.static_proxy;

/**
 * @author luguosong
 */
public class UserServiceProxy implements UserService{

    private UserService userService;

    public UserServiceProxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void addUser() {
        System.out.println("前置增强");
        userService.addUser();
        System.out.println("后置增强");
    }

    @Override
    public void editUser() {
        System.out.println("前置增强");
        userService.editUser();
        System.out.println("后置增强");
    }

    @Override
    public void deleteUser() {
        System.out.println("前置增强");
        userService.deleteUser();
        System.out.println("后置增强");
    }
}

测试代码:

Java
package com.luguosong.structural.proxy.static_proxy;

/**
 * @author luguosong
 */
public class Test {
    public static void main(String[] args) {
        UserService proxy = new UserServiceProxy(new UserServiceImpl());
        proxy.addUser();
    }
}

静态代理存在的问题#

  • 需要为所有想要被代理的服务(Service)编写代理类(Proxy),会导致代理类爆炸式增多。

动态代理#

JDK动态代理#

服务接口:

Java
package com.luguosong.structural.proxy.dynamic_proxy_jdk;

/**
 * @author luguosong
 */
public interface UserService {
    void addUser();

    void editUser();

    void deleteUser();
}

服务具体实现:

Java
package com.luguosong.structural.proxy.dynamic_proxy_jdk;

/**
 * @author luguosong
 */
public class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void editUser() {
        System.out.println("修改用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

在测试类中直接生成代理对象:

Java
package com.luguosong.structural.proxy.dynamic_proxy_jdk;

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

/**
 * @author luguosong
 */
public class Test {
    public static void main(String[] args) {
        UserService service = new UserServiceImpl();

        UserService serviceProxy = (UserService) Proxy.newProxyInstance(service.getClass().getClassLoader(),
                service.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("前置增强");
                        Object ret = method.invoke(service, args);
                        System.out.println("后置增强");
                        return ret;
                    }
                });

        serviceProxy.addUser();
    }
}

cglib动态代理#

使用cglib动态代理需要导入相关依赖:

XML
<dependencies>
    <!--❌这个依赖已经不维护了,JDK17调用会报错-->
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>

    <!--可以使用Spring内部的cglib实现,支持JDK17-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>6.1.8</version>
    </dependency>
</dependencies>

没有接口的服务类:

Java
package com.luguosong.structural.proxy.dynamic_proxy_cglib;

/**
 * @author luguosong
 */
public class UserServiceImpl {

    public void addUser() {
        System.out.println("添加用户");
    }

    public void editUser() {
        System.out.println("修改用户");
    }

    public void deleteUser() {
        System.out.println("删除用户");
    }
}

在测试类中动态创建代理对象:

Java
package com.luguosong.structural.proxy.dynamic_proxy_cglib;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;

/**
 * @author luguosong
 */
public class Test {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserServiceImpl.class);

        enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> {
            System.out.println("前置增强");
            Object ret = proxy.invokeSuper(obj, args1);
            System.out.println("后置增强");
            return ret;
        });

        UserServiceImpl userService = (UserServiceImpl)enhancer.create();
        userService.addUser();

    }
}

评论