AspectJ - 将try-finally块排除到方面

时间:2013-02-12 06:01:07

标签: java aop aspectj

我有很多这样的方法:

    Connection connection = null;
    try {
        connection = new Connection();
        connection.connect();
        .... // method body

    } finally {
        if (connection != null) {
            connection.disconnect();
        }
    }

我可以将此部分排除在方面(AspectJ)吗?

2 个答案:

答案 0 :(得分:2)

您可以将连接管理提取到around-advice中,并通过在Connection中公开它来使业务代码可以使用上下文ThreadLocal。使用静态属性定义公共类:

public class ConnectionHolder {
  public static final ThreadLocal<Connection> connection = new ThreadLocal<>();
}

在周围的建议中,您必须将ThreadLocal设置为打开的连接,然后确保您之后无条件地将其清除。这是ThreadLocal s最大的陷阱:将对象泄漏到不相关的上下文中。还要注意继承ThreadLocal的子线程(在WebSphere中存在一个问题)。

总而言之,ThreadLocal是一个非常脏的解决方案,但是其他任何东西都需要你去像Spring一样的依赖注入框架,配置请求范围的bean等,这将是一个很好的想法,但会对你进行更多的研究。

答案 1 :(得分:0)

或者,您可以使用template pattern提取连接管道以避免复制/粘贴。基本想法是这样的:

abstract ConnectionTemplate {
    private Connection connection = // ...

    /**
     * Method to be implementad by child classes
     */
    public abstract void businessLogicCallback(); 

    /**
     * Template method that ensure that mandatory plumbing is executed
     */
    public void doBusinessLogic() {
        try {
            openConnection();
            // fetch single result, iterate across resultset, etc
            businessLogicCallback();
        finally {
            closeConnection();
        }
    }

    void openConnection() {
        connection.open();
    }

    void closeConnection() {
        if (connection != null) {
            connection.close();
        }
    }
}

现在,实现类可以像

一样简单
class ImportantBusinessClass extends ConnectionTemplate {

    @Override
    public void businessLogicCallback() {
        // do something important
    }
}

你就像

一样使用它
ImportantBusinessClass importantClass = new ImportantBusinessClass();
importantClass.doBusinessLogic();      // opens connection, execute callback and closes connection

Spring框架在某些地方使用这种技术,特别是JdbcTemplate处理SQL,连接,行和域对象之间的映射等。请参阅GitHub中的source code以获取实现细节。< / p>