可以通过 Java 动态代理机制来实现一个通用的代理类,使它能够处理任意接口中包含的 set
和 get
方法,并且将属性值保存在一个内部的 Map
中。这样,每次调用 set
方法时,值会被存储到 Map
中,而调用 get
方法时,则会从 Map
中获取值。
下面是一个通用的解决方案:
1. 创建通用接口 XXX
java">public interface XXX {void setProperty(String value);String getProperty();
}
2. 创建 InvocationHandler
实现
我们将使用一个 Map<String, Object>
来存储属性值,其中键是属性名,值是对应的属性值。
java">import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class PropertyInvocationHandler implements InvocationHandler {private Map<String, Object> properties = new HashMap<>();@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String methodName = method.getName();// 检测是否是set方法if (methodName.startsWith("set") && args != null && args.length == 1) {String propertyName = methodName.substring(3); // 获取属性名properties.put(propertyName, args[0]); // 保存属性值到 Map 中return null;}// 检测是否是get方法if (methodName.startsWith("get") && args == null) {String propertyName = methodName.substring(3); // 获取属性名return properties.get(propertyName); // 从 Map 中获取属性值}throw new UnsupportedOperationException("Unsupported method: " + methodName);}
}
3. 通过代理实例化接口
使用 Proxy.newProxyInstance
来动态代理实现接口 XXX
。
java">import java.lang.reflect.Proxy;public class ProxyDemo {public static void main(String[] args) {// 创建处理器PropertyInvocationHandler handler = new PropertyInvocationHandler();// 创建代理对象XXX proxyInstance = (XXX) Proxy.newProxyInstance(XXX.class.getClassLoader(),new Class<?>[]{XXX.class},handler);// 测试代理对象的 set 和 get 方法proxyInstance.setProperty("Hello, World!");String value = proxyInstance.getProperty();System.out.println("Property Value: " + value); // 输出: Property Value: Hello, World!}
}
解释:
PropertyInvocationHandler
:实现了InvocationHandler
接口,通过invoke
方法拦截所有对set
和get
方法的调用。- 如果方法名以
set
开头,将属性名和属性值保存到Map<String, Object>
中。 - 如果方法名以
get
开头,则从Map
中取出对应的属性值并返回。
- 如果方法名以
- 代理对象创建:通过
Proxy.newProxyInstance
创建了XXX
接口的代理实例。 - 使用代理对象:可以通过代理对象调用
setProperty
和getProperty
方法,设置和获取属性值。
通用性:
这个实现是通用的,可以适用于任何包含 set
和 get
方法的接口。无论属性名是什么,只要是以 set
或 get
开头的方法,都可以通过这个代理来处理。
运行结果:
Property Value: Hello, World!
扩展:
如果接口中包含多个属性(例如 setName
、getName
、setAge
、getAge
等),该代码同样有效。属性名可以通过截取方法名的前缀来自动处理。
java">public interface Person {void setName(String name);String getName();void setAge(int age);int getAge();
}
java">public class ProxyPersonDemo {public static void main(String[] args) {PropertyInvocationHandler handler = new PropertyInvocationHandler();Person personProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),new Class<?>[]{Person.class},handler);personProxy.setName("Alice");personProxy.setAge(25);System.out.println("Name: " + personProxy.getName()); // 输出: Name: AliceSystem.out.println("Age: " + personProxy.getAge()); // 输出: Age: 25}
}
这样,动态代理可以灵活处理多个 set
和 get
方法,非常适合场景中使用属性接口的场合。