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
,就像前面提到的那样;它以最小的开销完成您想要的一切