当autowired 碰到transactional

今天碰到一个很sb的bug。

起因是:

@Controller
public class DemoController {

    @Autowired
    private DemoService demoService;
}

@Service
public class DemoService{

    @Autowired
    private DemoRepository demoRespository;
    
    @Transactional
    public void addUser(UserInfo userInfo){
         demoRespository.addUser(userInfo);
    }
}
//以上 run ok,然后我改为:
@Controller
public class DemoController {

    @Autowired
    private IDemoService demoService;
}

@Service
public class DemoService implements IDemoService{

    @Autowired
    private DemoRepository demoRespository;
    
    @Transactional
    public void addUser(UserInfo userInfo){
         demoRespository.addUser(userInfo);
    }
}
//===总是报无法注入的bug, not such bean之类的。不应该啊!
//===后来发现我个sb在另外一个controller中也用了DemoService,改为IDemoService就可以了
@Controller
@RequestMapping(value="/user")
public class UserController {
    
    @Autowired
    private DemoService demoService;
}

在解决这个问题中,查找了一些相关资料,

DemoService无法注入的解释是:如果有Transactional,spring会生成一个proxy class, implements IDemoService,类似:
public class ProxyServiceImpl implements IDemoService {

    private DemoService demoService; //instance of OriginalDaoImpl
    public void addUser(Object o){
       try{
            transaction.start();
            demoService.addUser(o);
            transaction.commit(); 
       }catch(Exception e){
            transaction.rollback();
       }finally{
            //clean up code
       }
    }
}

所以注入必须是interface。

还有一种办法:

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
//添加 proxy-target-class="true" 
这样可以直接注入
@Controller
public class DemoController {

    @Autowired
    private DemoService demoService;
}

解释是:

<tx:annotation-driven/> 元素的 "proxy-target-class" 属性值来控制是基于接口的还是基于类的代理被创建。

如果 "proxy-target-class" 属值被设置为 "true",那么基于类的代理将起作用(这时需要CGLIB库cglib.jar在CLASSPATH中)。如果 "proxy-target-class" 属值被设置为 "false" 或者这个属性被省略,那么标准的JDK基于接口的代理将起作用。

以上两种方法二选一,要不用第一种,不配置 "proxy-target-class"属性,代理基于接口,必须注入interface,

第二种:配置 "proxy-target-class" 属性 为true,代理基于类,注入class,

原文地址:https://www.cnblogs.com/zengyou/p/3152395.html