我们一直在使用@Autowired
加上基于Java的Spring配置并取得了一些成功,但现在,我们失去了控制权。每个人都开始在任何地方添加自动连接的依赖项,创建周期和奇怪的错误。
因此我们正在考虑使用构造函数注入和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然后尝试创建一个失败的代理,因为它找不到无参数的构造函数。
解决方案是什么?
答案 0 :(得分:5)
您有几种可能的解决方案
protected
no-arg构造函数在为类引入接口时,可以放弃CgLib的使用。然后Spring将能够使用JDK Dynamic Proxies来解决接口问题。它围绕一个已经存在的bean实例创建一个代理,该代理实现了它所包装的类的所有接口。这样,如果你的类有一个no-arg构造函数,那就不重要了。
在Spring 4.0中添加了支持以允许代理具有缺少的无参数构造函数的类(参见SPR-10594)。为了启用Spring版本的升级并将Objenesis添加到类路径中,Spring 4附带了自己的重新打包的cglib版本,因此不再需要它。
需要注意的一点是,如果在构造函数中进行空检查或初始化逻辑,那么你应该有一个没有逻辑的构造函数,在cglib创建实例的情况下它可能会失败。我怀疑它将null传递给所有构造函数参数(或者一些默认的基元)。
protected
无参数构造函数 Cglib需要能够创建一个用于包装实际类的实例。在你的类中有一个protected
构造函数就足够了,这样cglib就可以调用它。