• 当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,

  • 相关阅读:
    【转】使用setuptools简化Python模块的安装
    【转】CPU位数、核数、个数
    JS中的一些注意事项
    关于新浪微博在.net中的应用,配置极其使用
    [字符集]Unicode和UTF8之间的转换详解
    Const用法小结
    C++中虚析构函数的作用
    CTreeCtrl 的一点基础代码
    C2143: 语法错误 C4430: 缺少类型说明符 假定为 int 原因是没有包含头文件(含糊不清,以备查)
    mfc 窗口 分割
  • 原文地址:https://www.cnblogs.com/zengyou/p/3152395.html
Copyright © 2020-2023  润新知