我有一個由getter/setter方法的接口組成的對象模型。這些對象的實現是使用動態代理創建的,其中隱含字段的值(使用JavaBean命名約定)存儲在Map中。如何拆分兩個類之間的接口的實現
我想方法添加到這些接口提供業務邏輯(你知道,像一個真正的對象模型,而不是僅僅的POJO的集合)。
我首先想到的是創建一個實現每個接口,但只提供業務方法的實現的抽象類。然後,我會將這些實現與InvocationHandler中的Map配合使用,以提供接口的完整實現。
喜歡的東西:
interface ModelObject extends BaseModel {
void setFoo(String foo);
String getFoo();
void doSomething();
}
public abstract class ModelObjectImpl implements ModelObject {
@Override
public void doSomething()
{
// Do something
}
}
public class ModelObjectInvocationHander implements InvocationHandler {
Map<String, Object> fieldValues; // holds values for implied fields for getter setter
ModelObject modelObject; // holds reference to object implementing business methods
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Get implied field name for method name by removing "get"/"set" and lower casing next letter
String fieldName = getBeanNameForMethod(method.getName());
if (fieldValues.containsKey(fieldName)) {
return fieldValues.get(fieldName);
}
// Not a getter/setter so must be a business method. Delegate to implementation class
return method.invoke(modelObject, args);
}
}
像這樣的東西(但顯然更復雜的),只是我不能創建抽象類的實例會工作。我可以使BusinessObjectImpl非抽象,並添加永遠不會被調用的getter/setter方法的do-nothing實現,但這隻會使代碼變醜並導致維護問題。我也可以讓BusinessObjectImpl實際上不實現BusinessObject接口,但是當接口和「實現」不同步時,它打破了實現和接口之間的良好綁定,導致錯誤。
是否有任何偷偷摸摸的Java反射技巧,我可以用它來調用這些業務方法?
更新: 結合已有的Java動態代理框架和Javassist創建代理抽象實現類。這允許根據需要添加業務方法之前,根本沒有對現有模型接口進行任何更改。現在這個功能已經可以向對象添加行爲了。開發人員現在開始編寫真正的面向對象的代碼。
public class ModelObjectInvocationHandler implements InvocationHandler
{
public ModelObjectInvocationHandler(Class<ModelImplementation<? extends BaseModel>> implementationClass)
{
if (implementationClass != null)
{
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(implementationClass);
try
{
modelObject = (ModelObject) factory.create(new Class<?>[0], new Object[0]);
}
catch (Exception e)
{
// Exception handling
}
}
}
Map<String, Object> fieldValues; // holds values for implied fields for getter setter
ModelObject modelObject; // holds reference to object implementing business methods
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// Get implied field name for method name by removing "get"/"set" and lower casing next letter
String fieldName = getBeanNameForMethod(method.getName());
if (fieldValues.containsKey(fieldName))
{
return fieldValues.get(fieldName);
}
// Not a getter/setter so must be a business method. Delegate to implementation class
if (modelObject != null)
{
return method.invoke(modelObject, args);
}
return null;
}
}
在運行時,我掃描實現類,並創建一個Map<Class<? extends BaseModel>, Class<ModelImplementation>>
。在爲接口創建動態代理時,我在地圖中找到它的實現類並將其傳遞給InvocationHandler
。任何不匹配爲bean名稱的方法都會委派給實現類的代理。當然,它比這更復雜一點,因爲我必須考慮模型接口中的類層次結構和多重繼承,但理論是正確的。
同意。我正在使用基於[先前的問題/答案]的Javassist的解決方案(http://stackoverflow.com/questions/3291637/alternatives-to-java-lang-reflect-proxy-for-creating-proxies-of-抽象類) – DanN