Bootstrap

Java基础编程500题——动态代理

💥 该系列属于【Java基础编程500题】专栏,如您需查看Java基础的其他相关题目,请您点击左边的连接

目录

1. 使用Java动态代理实现一个简单的日志功能。

2. 使用Java动态代理实现方法调用的权限校验。

3. 使用Java动态代理实现方法的耗时统计。

4. 使用Java动态代理实现一个简单的缓存机制。

5. 使用Java动态代理实现方法调用次数限制。


 ✨✨  返回题目目录 ✨ ✨ 

Java基础编程500题


1. 使用Java动态代理实现一个简单的日志功能。

  1. 创建一个接口Operation,包含一个方法execute(String msg)。
  2. 实现Operation接口的OperationImpl类。
  3. 使用动态代理为OperationImpl类添加日志功能。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义一个操作接口
interface Operation {
    void execute(String msg);
}

// 实现操作接口的类
class OperationImpl implements Operation {
    @Override
    public void execute(String msg) {
        // 执行操作
        System.out.println("执行操作:" + msg);
    }
}

// 日志处理器,实现InvocationHandler接口
class LoggingHandler implements InvocationHandler {
    private Object target; // 被代理的对象

    public LoggingHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在方法执行前打印日志
        System.out.println("日志:方法 " + method.getName() + " 开始执行");
        // 执行实际的方法
        Object result = method.invoke(target, args);
        // 在方法执行后打印日志
        System.out.println("日志:方法 " + method.getName() + " 执行结束");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建目标对象
        Operation operation = new OperationImpl();
        // 创建代理对象
        Operation proxy = (Operation) Proxy.newProxyInstance(
                Operation.class.getClassLoader(),
                new Class[]{Operation.class},
                new LoggingHandler(operation)
        );
        // 通过代理对象调用方法
        proxy.execute("操作1");
    }
}

2. 使用Java动态代理实现方法调用的权限校验。

  1. 创建一个接口UserService,包含一个方法login(String username, String password)。
  2. 实现UserService接口的UserServiceImpl类。
  3. 使用动态代理为UserServiceImpl类添加权限校验功能。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义用户服务接口
interface UserService {
    void login(String username, String password);
}

// 实现用户服务接口的类
class UserServiceImpl implements UserService {
    @Override
    public void login(String username, String password) {
        // 执行登录操作
        System.out.println(username + " 登录成功");
    }
}

// 权限校验处理器,实现InvocationHandler接口
class AccessHandler implements InvocationHandler {
    private Object target; // 被代理的对象

    public AccessHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 进行权限校验
        if (args != null && args.length > 1 && "admin".equals(args[0])) {
            System.out.println("管理员登录,权限校验通过");
            return method.invoke(target, args); // 权限校验通过,执行方法
        } else {
            System.out.println("非管理员登录,权限校验不通过");
            return null; // 权限校验不通过,不执行方法
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建目标对象
        UserService userService = new UserServiceImpl();
        // 创建代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(
                UserService.class.getClassLoader(),
                new Class[]{UserService.class},
                new AccessHandler(userService)
        );
        // 通过代理对象调用方法
        proxy.login("admin", "123456");
        proxy.login("user", "123456");
    }
}

3. 使用Java动态代理实现方法的耗时统计。

  1. 创建一个接口TimeConsuming,包含一个方法calculate()。
  2. 实现TimeConsuming接口的TimeConsumingImpl类。
  3. 使用动态代理为TimeConsumingImpl类添加方法耗时统计功能。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义耗时操作接口
interface TimeConsuming {
    void calculate();
}

// 实现耗时操作接口的类
class TimeConsumingImpl implements TimeConsuming {
    @Override
    public void calculate() {
        try {
            // 模拟耗时操作
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 执行计算
        System.out.println("计算完成");
    }
}

// 耗时处理器,实现InvocationHandler接口
class TimeHandler implements InvocationHandler {
    private Object target; // 被代理的对象

    public TimeHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis(); // 开始时间
        Object result = method.invoke(target, args); // 执行方法
        long end = System.currentTimeMillis(); // 结束时间
        // 打印方法耗时
        System.out.println("方法耗时:" + (end - start) + " 毫秒");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建目标对象
        TimeConsuming timeConsuming = new TimeConsumingImpl();
        TimeConsuming proxy = (TimeConsuming) Proxy.newProxyInstance(
                TimeConsuming.class.getClassLoader(),
                new Class[]{TimeConsuming.class},
                new TimeHandler(timeConsuming)
        );
        proxy.calculate();
    }
}

4. 使用Java动态代理实现一个简单的缓存机制。

  1. 定义一个Calculator接口,包含一个calculate方法,该方法接收两个整数参数并返回它们的和。
  2. 实现该接口的CalculatorImpl类。
  3. 使用动态代理为CalculatorImpl类添加缓存功能,以避免重复计算相同的参数。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

// 定义计算器接口
interface Calculator {
    int calculate(int a, int b);
}

// 实现计算器接口
class CalculatorImpl implements Calculator {
    @Override
    public int calculate(int a, int b) {
        // 模拟计算过程
        return a + b;
    }
}

// 缓存处理器
class CacheHandler implements InvocationHandler {
    private Calculator target;
    private Map<String, Integer> cache = new HashMap<>();

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 构建缓存键
        String key = method.getName() + "_" + args[0] + "_" + args[1];
        // 检查缓存
        if (cache.containsKey(key)) {
            System.out.println("从缓存中获取结果");
            return cache.get(key);
        }
        // 执行计算
        Object result = method.invoke(target, args);
        // 存储结果到缓存
        cache.put(key, (Integer) result);
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Calculator calculator = new CalculatorImpl();
        Calculator proxy = (Calculator) Proxy.newProxyInstance(
                Calculator.class.getClassLoader(),
                new Class[]{Calculator.class},
                new CacheHandler(calculator)
        );
        // 调用代理方法
        System.out.println("计算结果:" + proxy.calculate(10, 20));
        System.out.println("计算结果:" + proxy.calculate(10, 20)); // 第二次调用会从缓存中获取结果
    }
}

5. 使用Java动态代理实现方法调用次数限制。

  1. 定义一个LimitedMethod接口,包含一个call方法。
  2. 实现该接口的LimitedMethodImpl类。
  3. 使用动态代理为LimitedMethodImpl类添加调用次数限制功能,当调用次数超过限制时,抛出异常。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义有限制的方法接口
interface LimitedMethod {
    void call();
}

// 实现有限制的方法接口
class LimitedMethodImpl implements LimitedMethod {
    @Override
    public void call() {
        System.out.println("方法被调用");
    }
}

// 调用次数限制处理器
class LimitHandler implements InvocationHandler {
    private LimitedMethod target;
    private int callCount = 0;
    private final int LIMIT = 3;

    public LimitHandler(LimitedMethod target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (callCount >= LIMIT) {
            throw new RuntimeException("调用次数超过限制");
        }
        callCount++;
        return method.invoke(target, args);
    }
}

public class Main {
    public static void main(String[] args) {
        LimitedMethod limitedMethod = new LimitedMethodImpl();
        LimitedMethod proxy = (LimitedMethod) Proxy.newProxyInstance(
                LimitedMethod.class.getClassLoader(),
                new Class[]{LimitedMethod.class},
                new LimitHandler(limitedMethod)
        );
        // 调用代理方法
        for (int i = 0; i < 5; i++) {
            try {
                proxy.call();
            } catch (RuntimeException e) {
                System.out.println(e.getMessage());
            }
        }
    }
}

;