весна и @transactional, это нормально? - PullRequest
1 голос
/ 10 ноября 2010

Я написал этот простой пример:

//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, вывод: false false.

Почему у меня такое поведение?Я знаю, что по умолчанию @Autowired классы синглетные, но почему в первом случае флаг все еще остается истинным?

Спасибо всем.

1 Ответ

5 голосов
/ 10 ноября 2010

Механизм @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);

Справка:

...