Java7-自定义方法装饰,无需默认委派所有、其他许多方法

Java7-自定义方法装饰,无需默认委派所有、其他许多方法,java,java-7,decorator,proxy-classes,invocationhandler,Java,Java 7,Decorator,Proxy Classes,Invocationhandler,我想修改接口,以便自定义关闭它(只是一个示例) 这意味着我想修饰PreparedStatement的现有实例,从而在调用close()时调用其他代码 为此,我需要默认实现PreparedStatementdecorator的所有tens方法,以便将调用委托给内部对象,就像done一样。缺点是它只需要大量的工作和代码,附加值很低 另一个选择是尝试使用Java,以便提供一个默认实现,在单个方法中为所有方法进行委托。如果存在自定义方法,则将调用定向到该方法。参见示例。 此解决方案的问题是,无法将自定义

我想修改接口,以便自定义关闭它(只是一个示例)


这意味着我想修饰
PreparedStatement
的现有实例,从而在调用
close()
时调用其他代码


为此,我需要默认实现
PreparedStatement
decorator的所有tens方法,以便将调用委托给内部对象,就像done一样。缺点是它只需要大量的工作和代码,附加值很低

另一个选择是尝试使用Java,以便提供一个默认实现,在单个方法中为所有方法进行委托。如果存在自定义方法,则将调用定向到该方法。参见示例。
此解决方案的问题是,无法将自定义方法标记为
@Override
,并且无法检查其签名的正确性,因为它需要一个抽象的
PreparedStatement
,而代理将无法实例化它

那么,这可以做到吗?怎么做?


*必须能够使用Java 7 max实现,但请随意提供Java 8答案。

据我所知,您希望为接口PreparedStatement提供具体实现。我能想到的唯一方法是创建实现接口的抽象类。通过这样做,您不需要从接口实现所有方法,您将获得所需的实现

我想试试这样的东西:

public abstract class MyPreparedStatement implements PreparedStatement {

@Override
public void close() throws SQLException {
    System.out.println("Closing");
}

public static void main(String[] args) throws SQLException {
    Connection con = null;
    MyPreparedStatement statement = (MyPreparedStatement) con.prepareStatement("sql");
}
}

如果您没有访问这些方法的权限来对它们执行通常的继承操作,那么您可以通过面向方面编程、利用Spring框架方面功能或方面功能来完成您正在尝试执行的操作,以提供有关所需方法的建议

一个简单的方面基本上可以归结为:

@Aspect
public class MyAspect {

    @Pointcut("execution(* *(..))") //Replace expression with target method; this example 
    //will hit literally every method ever.
    public void targetmethod() {}; //Intentionally blank.
    //AspectJ uses byte code manipulation (or "black magic voodoo", if you 
    // will) to make this method a surrogate for any real one that matches the pointcut

    @Before("targetmethod()") //Or @After, or @Around, etc...
    public void doStuff() throws Throwable {
        //Put your code here
    }
}
将方面组合在一起后,将它们添加到aop.xml并编织方面(您可以在编译时使用适当的构建管理器配置,或者在运行时使用
java-javaagent:/path/to/aspectjweaver.jar运行aspectjweaver来实现这一点)


不过,这确实有一个免责声明:对java.*类执行类似操作可以让您以新的、有趣的方式打破事物,并带来您正在引入的所有副作用(事实上,AspectJWeaver默认情况下拒绝编织到java.*类中,尽管您可以覆盖该设置)。非常清楚自己在做什么,并明智地使用方面和方面的方法。

您能否更清楚地解释一下
代理解决方案缺少什么?考虑这样的事情,这依赖于AOP风格的钩子:

final PreparedStatement original = ...;
final InvocationHandler delegator = new InvocationHandler() {

  void onClose() {
    /* do stuff */
  }

  Object invoke(final Object proxy, final Method method, final Object[] args) {
    if (method.getName().equals("close")) {
      onClose();
    }

    return method.invoke(original, args);
  }
};
final PreparedStatement wrapped = (PreparedStatement) Proxy.newProxyInstance(this.getClass().getClassLoader(),
    new Class<?>[] { PreparedStatement.class }, delegator);
final PreparedStatement original=。。。;
final InvocationHandler delegator=new InvocationHandler(){
void onClose(){
/*做事*/
}
对象调用(最终对象代理、最终方法、最终对象[]参数){
if(method.getName().equals(“close”)){
onClose();
}
返回方法.invoke(原始,args);
}
};
final PreparedStatement wrapped=(PreparedStatement)Proxy.newProxyInstance(this.getClass().getClassLoader(),
新类[]{PreparedStatement.Class},委托人);

自定义关闭是什么意思,请您详细解释一下,因为这是编写装饰器的主键。您可以使用Mockito吗?您可以使用AOP实现功能。但是有一个问题,为什么需要修饰
PreparedStatement
PreparedStatement
只是一个有许多方法的接口的例子。一种可能是使用某种支持它的java方言。Lombok可能是最容易与普通java集成的,我认为您错过了
Decorator
的概念。我无法控制收到的
PreparedStatement
的实例。我只是控制如何使用它。您的解决方案将导致ClassCastException。是的,很抱歉,确实错过了它。带有
@Override
的close方法的确切签名在哪里?您是否在询问该方法的切入点应该是什么?这完全取决于你希望你的相位接触到哪种接近的方法。类似于
“call(public java.sql.PreparedStatement+.close(…)”
的内容应该与任何PreparedStatement或其子类上的
close()
匹配。可能有用。假设讨论的方法接收多个参数。现在需要通过反射调用自定义方法(为了不手动转换参数),对吗?所以,这意味着在编译时,没有人调用自定义close方法,对吗?因此,这意味着有人可以认为他可以更改自定义
close
方法的签名。我的目的是使自定义方法与实际接口
PreparedStatement
——最好是通过
@Override
。将自定义方法绑定到接口的另一个原因是在执行搜索时找到它。@AlikElzin kilaka那么显而易见的解决方案是编写一个委托
PreparedStatementDecorator
,就像前面提到的那样;它以最小的开销完成您想要的一切