Java设计问题,其中行为附加到注释

Bhu*_*van 6 java annotations dependency-injection transactions jpa-2.0

假设我使用注释JPA来使用@transactions.

因此,为了让任何方法在一个事务下运行,我添加了一个@transaction注释,BINGO我的方法在一个事务下运行.

为了实现上述目标,我们需要interface为类提供一个,并且实例由一些容器管理.
此外,我应该始终从接口引用调用该方法,以便代理对象可以启动事务.所以我的代码看起来像:

class Bar {
   @Inject
   private FooI foo;
   ...
   void doWork() {
      foo.methodThatRunUnderTx();
   }
}
class FooImpl implements FooI {
   @Override
   @Transaction
   public void methodThatRunUnderTx() {
       // code run with jpa context and transaction open
   }
}
interface FooI {
    void methodThatRunUnderTx();
}
Run Code Online (Sandbox Code Playgroud)

好,好

现在让我们说methodThatRunUnderTx两个逻辑操作

[1]调用一些服务(长请求/响应周期,比如5秒)并获取结果

[2]执行一些jpa实体修改

既然这个方法调用很长,我们不想长时间保持事务处理,所以我们更改代码,以便[2]在单独的tx中发生并且 methodThatRunUnderTx不会在事务中运行

因此,我们将删除@TransactionmethodThatRunUnderTx和在类中添加另一种方法@transaction让我们说新的方法是methodThatRunUnderTx2,现在调用此方法从methodThatRunUnderTx我们必须把它注入本身并添加一个方法,接口,这样的呼叫通过代理对象发生.

所以现在我们的代码看起来像:

class Bar {
   @Inject
   private FooI foo;
   ...
   void doWork() {
      foo.methodThatRunUnderTx();
   }
}
class FooImpl implements FooI {
   @Inject
   private FooI self;
   @Override
   //@Transaction -- remove transaction from here
   public void methodThatRunUnderTx() {
      ...
     self.methodThatRunUnderTx2();// call through proxy object
   }
   @Override
   @Transaction //add transaction from here
   public void methodThatRunUnderTx2() {
       // code run with jpa context and transaction open
   }
}
interface FooI {
    void methodThatRunUnderTx();
    void methodThatRunUnderTx2();
}
Run Code Online (Sandbox Code Playgroud)

现在问题

我们已经methodThatRunUnderTx2()公众通过interface.

但它不是我们想要暴露的东西,FooI而不是从外面调用它们.

有什么建议可以解决吗?

Dra*_*vic 1

这就是为什么现代容器不需要实现任何接口 - 然后通过动态子类创建代理或使用字节码检测。

因此,设计问题的解决方案很简单:实现一个包含事务方法的帮助器类,并将其注入到实现该接口的类(以及可以从中受益的任何其他类)。