设计模式之代理模式

目录

定义

代理对象作为客户端和真实对象之间的中介,替代真实对象处理请求,实现对访问的控制和功能增强。客户端通过代理间接操作真实对象,二者通常实现相同接口。

结构

适用场景

1)远程代理为一个对象在不同的地址空间提供局部代表

2)虚拟代理根据需要创建开销很大的对象

3)安全代理控制对原始对象的访问

4)日志代理记录操作行为

使用实例

这里以日志代理为例,说明java中代理的几种方式。

1、静态代理

2、JDK动态代理

3、Cglib代理

复制代码
/**
 * 定义业务接口
 */
public interface UserService {

    void addUser(String username);

    void deleteUser(String userId);

}

public class UserServiceImpl implements UserService{

    @Override
    public void addUser(String username) {
        System.out.println("真实操作:添加用户 " + username);
    }

    @Override
    public void deleteUser(String userId) {
        System.out.println("真实操作:删除用户ID " + userId);
    }

}

/**
 * 定义静态代理类
 */
public class UserServiceProxy implements UserService {

    private final UserService target;

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

    @Override
    public void addUser(String username) {
        System.out.println("静态代理,【前置日志】调用addUser,参数: " + username);
        target.addUser(username); // 调用真实对象
        System.out.println("静态代理,【后置日志】addUser执行完成");
    }

    @Override
    public void deleteUser(String userId) {
        System.out.println("静态代理,【前置日志】调用deleteUser,参数: " + userId);
        target.deleteUser(userId);
        System.out.println("静态代理,【后置日志】deleteUser执行完成");
    }

}

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

/**
 * 定义JDK动态代理核心处理类
 */
public class LoggingHandler implements InvocationHandler {

    private final Object target;

    public LoggingHandler(Object target) {
        if (target == null) {
            throw new IllegalArgumentException("Target object cannot be null");
        }
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK,调用方法: " + method.getName());
        return method.invoke(target, args);
    }
}

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * 定义Cglib代理核心处理类
 */
public class LogInterceptor implements MethodInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LogInterceptor.class);

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        logger.info("Cglib,方法调用开始 => {}.{}()", obj.getClass().getSuperclass().getSimpleName(), method.getName());
        Object result = proxy.invokeSuper(obj, args);
        logger.info("Cglib,方法调用结束 <= {}", method.getName());
        return result;
    }

}

测试

复制代码
import net.sf.cglib.proxy.Enhancer;

import java.lang.reflect.Proxy;

public class Client {

    public static void main(String[] args) {
        // 静态代理
        UserService realService = new UserServiceImpl();
        UserService proxy = new UserServiceProxy(realService);
        proxy.addUser("张三");
        proxy.deleteUser("100001");

        // jdk动态代理
        UserService jdkProxy = (UserService) Proxy.newProxyInstance(
                UserService.class.getClassLoader(),
                new Class[]{UserService.class},
                new LoggingHandler(realService)
        );
        jdkProxy.addUser("Alice");
        jdkProxy.deleteUser("100002");

        // Cglib代理(针对类)
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserServiceImpl.class);
        enhancer.setCallback(new LogInterceptor());

        UserService cglibProxy = (UserService) enhancer.create();
        cglibProxy.addUser("张五");
        cglibProxy.deleteUser("100003");
    }

}
相关推荐
我命由我123452 小时前
Kotlin 数据容器 - List(List 概述、创建 List、List 核心特性、List 元素访问、List 遍历)
java·开发语言·jvm·windows·java-ee·kotlin·list
武子康4 小时前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
YuTaoShao6 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
源码_V_saaskw7 小时前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友
超浪的晨7 小时前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
双力臂4047 小时前
Spring Boot 单元测试进阶:JUnit5 + Mock测试与切片测试实战及覆盖率报告生成
java·spring boot·后端·单元测试
Edingbrugh.南空8 小时前
Aerospike与Redis深度对比:从架构到性能的全方位解析
java·开发语言·spring
QQ_4376643148 小时前
C++11 右值引用 Lambda 表达式
java·开发语言·c++
永卿0018 小时前
设计模式-迭代器模式
java·设计模式·迭代器模式
使二颗心免于哀伤8 小时前
《设计模式之禅》笔记摘录 - 10.装饰模式
笔记·设计模式