代码之家  ›  专栏  ›  技术社区  ›  Aaron Digulla

Spring Java配置,@Autowire vs.构造函数注入,@Transactional和CGLIB

  •  3
  • Aaron Digulla  · 技术社区  · 10 年前

    我们一直在使用 @Autowired 加上基于Java的Spring配置取得了一些成功,但现在,我们正在失去控制。每个人都开始到处添加自动连线的依赖关系,从而产生循环和奇怪的bug。

    因此,我们正在考虑使用Spring配置的构造函数注入和自动布线。

    旧版本:

    class Bean {
       @Autowired Foo foo;
    }
    
    @Configuration
    @Import( FooCfg.class )
    class BeanCfg {
       @Bean public Bean bean() { return new Bean(); }
    }
    

    新建:

    class Bean {
       public Bean(Foo foo) {...}
    }
    
    @Configuration
    class BeanCfg {
       @Autowired FooCfg fooCfg;
       @Bean public Bean bean() { return new Bean(fooCfg.foo()); }
    }
    

    这非常有效(它驱使人们拆分bean,而不是创建带有10个以上构造函数参数的怪物)。

    但当 Bean 具有带注释的方法 @Transactional 因为CGLIB然后尝试创建一个代理,但由于找不到无参数构造函数而失败。

    解决方案是什么?

    1 回复  |  直到 10 年前
        1
  •  5
  •   M. Deinum    10 年前

    你有几个可能的解决方案

    1. 介绍类的接口
    2. 将Spring版本升级至至少4.0
    3. 添加 protected 无参数构造函数

    介绍接口

    在为类引入接口时,可以放弃CgLib的使用。然后,Spring将能够使用围绕接口工作的JDK动态代理。它围绕一个已经存在的bean实例创建一个代理,该代理实现了它所包装的类的所有接口。这样,类是否具有无参数构造函数就无关紧要了。

    升级到Spring 4

    在Spring 4.0中添加了支持,以允许代理缺少无参数构造函数的类(请参见 SPR-10594 ). 要启用此升级,请使用Spring版本并添加 Objenesis 对于您的类路径,Spring4自带重新打包的cglib版本,因此不再需要它了。

    需要注意的一点是,如果在构造函数中执行null检查或init逻辑,那么应该有一个没有逻辑的构造函数,在cglib创建实例的情况下,它可能会失败。我怀疑它会将null传递给所有构造函数参数(或原语的一些默认值)。

    补充 受保护的 无参数构造函数

    Cglib需要能够创建用于包装实际类的实例。有一个 受保护的 构造函数,以便cglib可以调用它。