青春有我
其他答案已经提出了惯用的方法。另一个想法是动态代理通过访问检查来修饰 API。本质上,您生成一个代理 API,该 API 对方法调用进行额外检查以实现某种形式的访问控制。实施示例:package com.example;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Proxy;@FunctionalInterfacepublic interface ACL<P, Q> { boolean allowed(P accessor, Q target, Method method, Object[] args); class ACLException extends RuntimeException { ACLException(String message) { super(message); } } @SuppressWarnings("unchecked") default Q protect(P accessor, Q delegate, Class<Q> dType) { if (!dType.isInterface()) { throw new IllegalArgumentException("Delegate type must be an Interface type"); } final InvocationHandler handler = (proxy, method, args) -> { if (allowed(accessor, delegate, method, args)) { try { return method.invoke(delegate, args); } catch (InvocationTargetException e) { throw e.getCause(); } } else { throw new ACLException("Access denies as per ACL"); } }; return (Q) Proxy.newProxyInstance(dType.getClassLoader(), new Class[]{dType}, handler); }}用法示例:package com.example;import java.lang.reflect.Method;public class Main { interface API { void doAlpha(int arg); void doBeta(String arg); void doGamma(Object arg); } static class MyAPI implements API { @Override public void doAlpha(int arg) { System.out.println("Alpha"); } @Override public void doBeta(String arg) { System.out.println("Beta"); } @Override public void doGamma(Object arg) { System.out.println("Gamma"); } } static class AlphaClient { void use(API api) { api.doAlpha(100); api.doBeta("100"); api.doGamma(this); } } public static class MyACL implements ACL<AlphaClient, API> { @Override public boolean allowed(AlphaClient accessor, API target, Method method, Object[] args) { final String callerName = accessor.getClass().getName().toLowerCase(); final String methodName = method.getName().toLowerCase().replace("do", ""); return callerName.contains(methodName); } } public static void main(String[] args) { final MyACL acl = new MyACL(); final API api = new MyAPI(); final AlphaClient client = new AlphaClient(); final API guardedAPI = acl.protect(client, api, API.class); client.use(guardedAPI); }}笔记:不一定accessor是客户端对象本身,它可以是帮助 ACL 识别客户端的字符串键或令牌。这里的 ACL 实现是基本的,更有趣的实现可能是从某个文件读取 ACL 的实现,或者使用方法和客户端注释作为规则的实现。如果你不想为API类定义接口,可以考虑使用javassist这样的工具来直接代理类。考虑其他流行的面向方面编程解决方案