我试图找出是否有可能创建Java动态代理来自动关闭自动关闭资源,而不必记住用try资源块嵌入这些资源。
例如,我有一个JedisPool,它有一个getResource方法,可以这样使用:
try(Jedis jedis = jedisPool.getResource() {
// use jedis client
}
现在我做了这样的事情:
class JedisProxy implements InvocationHandler {
private final JedisPool pool;
public JedisProxy(JedisPool pool) {
this.pool = pool;
}
public static JedisCommands newInstance(Pool<Jedis> pool) {
return (JedisCommands) java.lang.reflect.Proxy.newProxyInstance(
JedisCommands.class.getClassLoader(),
new Class[] { JedisCommands.class },
new JedisProxy(pool));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (Jedis client = pool.getResource()) {
return method.invoke(client, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw e;
}
}
}
现在,每次我在Jedis(JedisCommands)上调用method时,这个方法都会被传递给代理,代理从池中获取一个新的客户端,执行这个方法并将这个资源返回到池中。
它工作得很好,但当我想在客户机上执行多个方法时,每个方法的资源都会从池中取出并再次返回(这可能很耗时)。你知道如何改进吗?
我不认为这是朝着正确的方向前进。毕竟,开发人员应该习惯于正确处理资源,并且IDE/编译器能够在未使用try(...){}
处理自动关闭资源时发出警告...
然而,创建一个代理来装饰所有调用,并添加一种方法来装饰一批多个操作作为一个整体,这是一项一般性的任务,因此,它有一个通用的解决方案:
class JedisProxy implements InvocationHandler {
private final JedisPool pool;
public JedisProxy(JedisPool pool) {
this.pool = pool;
}
public static JedisCommands newInstance(Pool<Jedis> pool) {
return (JedisCommands) java.lang.reflect.Proxy.newProxyInstance(
JedisCommands.class.getClassLoader(),
new Class[] { JedisCommands.class },
new JedisProxy(pool));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (Jedis client = pool.getResource()) {
return method.invoke(client, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
public static void executeBatch(JedisCommands c, Consumer<JedisCommands> action) {
InvocationHandler ih = Proxy.getInvocationHandler(c);
if(!(ih instanceof JedisProxy))
throw new IllegalArgumentException();
try(JedisCommands actual=((JedisProxy)ih).pool.getResource()) {
action.accept(actual);
}
}
public static <R> R executeBatch(JedisCommands c, Function<JedisCommands,R> action){
InvocationHandler ih = Proxy.getInvocationHandler(c);
if(!(ih instanceof JedisProxy))
throw new IllegalArgumentException();
try(JedisCommands actual=((JedisProxy)ih).pool.getResource()) {
return action.apply(actual);
}
}
}
请注意,池的类型转换
现在你可以像这样使用它了
JedisCommands c=JedisProxy.newInstance(pool);
c.someAction();// aquire-someaction-close
JedisProxy.executeBatch(c, jedi-> {
jedi.someAction();
jedi.anotherAction();
}); // aquire-someaction-anotherAction-close
ResultType foo = JedisProxy.executeBatch(c, jedi-> {
jedi.someAction();
return jedi.someActionReturningValue(…);
}); // aquire-someaction-someActionReturningValue-close-return the value
批处理执行要求实例是代理,否则会引发异常,因为很明显,该方法无法保证具有未知生命周期的未知实例的特定行为。
此外,开发人员现在必须了解代理和批处理执行功能,就像不使用代理时必须了解资源和
try(…){}
语句一样。另一方面,如果没有,在不使用批处理方法的情况下调用代理上的多个方法时,它们会失去性能,而在不使用try(…){}
在实际的非代理资源上调用多个方法时,它们会让资源泄漏…
最终,您将拥有自己的“事务管理器”,在该管理器中,您通常会立即将对象返回到池中,但如果您启动了“事务”,则在“提交”该“事务”之前,对象不会返回到池中。
突然之间,由于使用了手工构建的自定义机制,使用try-with-Resources
的问题变成了实际问题。
与资源专家一起使用try:
Jedis
代码,并(希望)认为“所以这一定是使用这个的正确方式”欺骗:
你的建议优点(如果我忘记了什么,你可以告诉我):
欺骗:
[jr]edis
或你的项目,所以我不能说这是否真的是一个问题)如果你认为我没有提出有效的观点,请告诉我。否则,我的断言将仍然是“你有一个寻找问题的‘解决方案’”。
问题内容: 我正在编写一个连接到网站并从中读取一行的应用程序。我这样做是这样的: 好吗?我的意思是,我在最后一行关闭了BufferedReader,但没有关闭InputStreamReader。我是否应该从connection.getInputStream创建一个独立的InputStreamReader,并从独立的InputStreamReader创建一个BufferedReader,而不是关闭所
本文向大家介绍Java使用 try-with-resources 实现自动关闭资源的方法,包括了Java使用 try-with-resources 实现自动关闭资源的方法的使用技巧和注意事项,需要的朋友参考一下 1、 在Java1.7之前,我们需要通过下面这种方法, 在finally中释放资源,这种方法有点繁琐。 2、在java1.7之后,可以使用try-with-resources实现自动关闭资
在学习《 Java try catch finally语句》一节后我们可以发现,当程序使用 finally 块关闭资源时,程序会显得异常臃肿,例如以下代码。 Java 7 以前,上面程序中的 finally 代码块是不得不写的“臃肿代码”,为了解决这种问题,Java 7 增加了一个新特性,该特性提供了另外一种管理资源的方式,这种方式能自动关闭文件,被称为 自动资源管理(Automatic Reso
我在windows 7中安装了android Studio,但它在打开后立即关闭。我还安装了java jdk并添加了一个JDK_HOME环境变量,但android Studio会在几秒钟后自行关闭。
问题内容: 有人可以推荐几个不错的网站/ bloogs / RSS / Podcast,让对Java感兴趣的人可以随时了解最新趋势吗? (我在考虑像Ajaxian.com这样的Java语言) 一如既往,我们将永远感谢您的帮助。 问题答案: Java Posse播客:http : //www.javaposse.com/
我是java新手。我正在尝试编写一个java代理。在使用演示应用程序运行时,它会失败,并显示以下消息: 下面是代码和pom文件:https://gist.github.com/proywm/f27b72d01aa66afc7f0f8c098e33e914 你能告诉我如何解决这个问题吗?