i wrote this simple example:
//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();
}
}
And this is my try:
TestService s1=context.getBean(TestService.class);
TestService s2=context.getBean(TestService.class);
List<Test> list=s1.useController();
System.out.println(s1.flag+" "+s2.flag);
Now the strange behaviour (im very new with spring):
- If i declare
@Transactional
the method "useController()", the output is: true true - If i move
@Transactional
fromTestService
toTestControllerImp
, and i declare "findAll()" with@Transactional
, the output is: false false.
Why i have this behaviour? I know by default @Autowired
classes are singletone, but why in the first case the flag still remains true?
Thanks all.
The @Transactional mechanism works on JDK proxies per default and those work on interfaces only.
So if you let
TestService
be an interface andTestServiceImpl
be its implementation, then the above code should work.e.g. change the class declaration to this:
but the test code must reference the interface, not the class:
Reference:
<tx:advice/>
settings (Spring Reference)@Transactional
(Spring Reference)