如何拆分两个类之间接口的实现

时间:2013-07-13 21:50:56

标签: java reflection dynamic-proxy

我有一个由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 Reflection技巧来调用这些业务方法吗?

更新: 结合使用已经存在的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名称匹配的方法都会委托给实现类的代理。当然,它有点复杂,因为我必须在模型接口中考虑类层次结构和多重继承,但理论是合理的。

2 个答案:

答案 0 :(得分:0)

我不知道会有任何标准的Java反射技巧。您可以在类加载时使用cglibjavaassist动态扩展抽象类。这会稍微提高性能,因为不再需要Proxy个对象。相反,您可以在创建新类时直接实现getter / setter方法。

第三种方式,没有这些技巧,将采用委托模式:

public class ModelObjectImpl implements ModelObject {
  private final ModelObject delegate;

  public ModelObjectImpl(ModelObject delegate) { 
    this.delegate = delegate;
  }

  @Override
  public void doSomething() { /* Do something */ }

  @Override
  public String getFoo() { return delegate.getFoo(); }

  @Override
  public void setFoo(String foo) { delegate.setFoo(foo); }
}

将代理(实现接口的getter / setter方法)提供给构造函数delegate参数。然而,虽然这看起来比存根方法(至少对我来说)更好,但它仍然是重复的代码。因此,如果您真的想拥有这样的动态类,请使用动态字节码生成。

<强>参考文献:

答案 1 :(得分:0)

这样做的一种方法是在新界面中定义所有“附加”或“业务”方法的合同,例如:

interface ModelObjectExtension {
    void doSomething();
}

interface ModelObject extends ModelObjectExtension {
    void setFoo(String foo);
    String getFoo();
}

public abstract class ModelObjectExtensionImpl implements ModelObjectExtension {

    @Override
    public void doSomething()
    {
        // Do something
    }
}

public class ModelObjectImpl extends ModelObjectExtension { 
    // whatever your current implementation is...
}

最后你可以在你的处理程序中使用以下来调用扩展方法:

((ModelObjectExtension) modelObject).doSomething();