1

私はこの簡単な例を書きました:

//file TestController.java
public interface TestController {

    public List<Test> findAll();

}

//file TestControllerImp.java
@Controller
public class TestControllerImp implements TestController{

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory=sessionFactory;
    }

    public List<Test> findAll() {
        return sessionFactory.getCurrentSession().createQuery("from Test").list();
    }

}

//file TestService.java
@Service
public class TestService {

    @Autowired
    private TestController controller;

    public boolean flag=true;

    public void setController(TestController controller){
        this.controller=controller;
    }

    @Transactional
    public List<Test> useController(){
        flag=false;
        return controller.findAll();
    }

}

そして、これは私の試みです:

TestService s1=context.getBean(TestService.class);
TestService s2=context.getBean(TestService.class);
List<Test> list=s1.useController();
System.out.println(s1.flag+"  "+s2.flag);

今、奇妙な振る舞い(私は春に非常に新しいです):

  1. @Transactionalメソッド「useController()」を宣言すると、出力は次のようになります。true true
  2. @TransactionalからTestServiceに移動しTestControllerImp、「findAll()」をで宣言すると@Transactional、出力はfalsefalseになります。

なぜ私はこの振る舞いをするのですか?デフォルトでクラスがシングルトーンであることは知っています@Autowiredが、最初のケースでフラグがまだ真のままであるのはなぜですか?

皆さんありがとう。

4

1 に答える 1

5

@Transactionalメカニズムは、デフォルトでJDKプロキシで機能し、それらはインターフェースでのみ機能します。

したがってTestService、インターフェイスにしTestServiceImplてその実装にする場合は、上記のコードが機能するはずです。

たとえば、クラス宣言を次のように変更します。

@Service
public class TestServiceImpl implements TestService {

ただし、テストコードは、クラスではなくインターフェイスを参照する必要があります。

// this code remains unchanged
TestService s1=context.getBean(TestService.class);
TestService s2=context.getBean(TestService.class);

参照:

于 2010-11-10T10:42:32.183 に答える