【问题标题】:Java. Reuse try-finally construction with return爪哇。重用 try-finally 构造并返回
【发布时间】:2012-08-15 12:53:15
【问题描述】:

看看这段代码:

IDfSessionManager manager = DfcSessionManager.getSessionManager();
    try {
        IDfSession session = manager.getSession(DfsUtils.getCurrentRepository());
        ...
        return somewhat; //May be without return statement
    } finally {
        if (session != null) {
            manager.release(session);
        }
    }

这样的结构会重复很多次,并围绕着不同的代码。这可以是带有或不带有 return 语句的方法。 我想为这个 try-finally 块做一些可重用的东西。

我已经想到了这样的认识。

public abstract class ISafeExecute<T> {

private IDfSession session = null;

protected abstract T execute() throws DfException;

public T executeSafely() throws Exception {
    IDfSessionManager manager = DfcSessionManager.getSessionManager();
    try {
        session = manager.getSession(DfsUtils.getCurrentRepository());
        return execute();
    } finally {
        if (session != null) {
            manager.release(session);
        }
    }
}

public IDfSession getSession() {
    return session;
}

}

会话字段是使用公共 getter 生成的。

我们可以像这样使用这个类(返回对象):

return new ISafeExecute<String>() {
        @Override
        public String execute() throws DfException {
            return getSession().getLoginTicket();
        }
    }.executeSafely();

或者没有返回对象:

    new ISafeExecute() {
        @Override
        public Object execute() {
            someMethod();
            return null;
        }
    }.executeSafely();

【问题讨论】:

  • 第一个代码 sn-p 甚至无法编译。您必须在 try 块之外声明 session 才能在 finally 块中使用它。

标签: java try-catch code-reuse


【解决方案1】:

您可以使用Runnable&lt;T&gt; 构建一个机制来执行此操作(将一个函数注入另一个函数):

public void runInSession(Runnable<IDfSession> runnable) {

    IDfSession session = null;
    try {

        session = manager.getSession(DfsUtils.getCurrentRepository());
        runnable.run(session);        

    } finally {
        if (session != null) {
            manager.release(session);
        }
    }

}

您也可以使用更多泛型来使您能够返回值。我这里缺少 Java 编译器,但我对语法有点不确定。

编辑,我看到你的编辑:

使用自定义的ISafeExecute 界面可能比使用Runnable&lt;T&gt; 更简洁,但想法保持不变。您可以构建它,以便可以优雅地放置返回值(或错误):

interface ISafeExecute<T> {

  void execute(IDfSession session);

  T getResult();

  Exception getException();

}

mySafeExecute.execute(session);

if(mySafeExecute.getException() == null) {
    return mySafeExecute.getResult();
} else {
    // runtime exception or declaration in method
    // signature
    throw new RuntimeException(mySafeExecute.getException());
}

【讨论】:

  • 太棒了!但是 Callable 而不是 Runnable.
  • @Mudu 有 Callable - 它只返回 T 类型的结果,而 runnable 没有
  • Spring 在 HibernateTemplate 和 JdbcTemplate 中采用了这种方法。通常称为“回调”模式。
【解决方案2】:

我做出了这样的决定:

 public abstract class SafeExecute<T> {

    protected IDfSession session = null;

    public T executeSafely() throws Exception {
        IDfSessionManager manager = DfcSessionManager.getSessionManager();
        try {
            session = manager.getSession(DfsUtils.getCurrentRepository());
            return logic();
        } finally {
            if (session != null) {
                manager.release(session);
            }
        }
    }

    protected abstract T logic() throws Exception;

}

然后通过扩展这个类:

public class Service extends SafeExecute<String> {

    public String getLoginTicket() throws Exception {
        return executeSafely();
    }

    @Override
    protected String logic() throws Exception {
        //TODO implement
    }
}

【讨论】:

    猜你喜欢
    • 2015-02-16
    • 2016-03-28
    • 2014-04-27
    • 2017-07-20
    • 2018-11-05
    • 2014-02-28
    • 2013-08-31
    • 2016-11-08
    • 1970-01-01
    相关资源
    最近更新 更多