Wicket @SpringBean和Spring @Autowired通过构造函数注入

Tom*_*rko 5 java spring wicket dependency-injection

我有一个Wicket面板,我想在其中使用@SpringBean注入bean

public class SomePanel extends Panel {

  @SpringBean
  private BlogSummaryMailGenerator blogSummaryMailGenerator;

}
Run Code Online (Sandbox Code Playgroud)

但是这个BlogSummaryMailGenerator通过如下定义的构造函数注入:

@Component
public class BlogSummaryMailGenerator {

  private BlogRepository blogRepository;
  private BlogPostRepository blogPostRepository;

  @Autowired
  public BlogSummaryMailGenerator(BlogRepository blogRepository,
                                BlogPostRepository blogPostRepository) {
    this.blogRepository = blogRepository;
    this.blogPostRepository = blogPostRepository;
  }
}
Run Code Online (Sandbox Code Playgroud)

当SomePanel被实例化时,我得到一个例外

Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499) ~[cglib-3.1.jar:na]
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) ~[cglib-3.1.jar:na]
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285) ~[cglib-3.1.jar:na]
at org.apache.wicket.proxy.LazyInitProxyFactory.createProxy(LazyInitProxyFactory.java:191) ~[wicket-ioc-7.2.0.jar:7.2.0]
Run Code Online (Sandbox Code Playgroud)

将空的no-args构造函数添加到BlogSummaryMailGenerator可以解决此问题,但仅添加此类代码以使注入工作是错误的,我想避免它.

有关如何通过构造函数使用注入使@SpringBean与bean一起工​​作的任何建议吗?

mar*_*n-g 6

真正的问题在于CGLIB.它需要一个默认构造函数才能创建代理实例.真正的Spring bean是由Spring单独创建的,没有这样的限制.CGLIB所需的默认构造函数甚至可以private记得.

另一种解决方案是为此bean使用接口.然后Wicket将使用JDK代理而不是CGLIB,在这种情况下,实现中不需要默认构造函数.


Mar*_*tek 6

解决方案

为了能够@SpringBeanWicket组件中利用构造函数注入,您只需将Objenesis添加到您的编译时依赖项中。

解释

Objenesis是一个鲜为人知的字节码操作库(与CGLIBWicket一起提供)能够为没有默认(无参数)构造函数的类创建代理对象。如果您将它作为编译依赖项添加到您的项目中,那么Wicket将切换其内部可延迟初始化的代理创建逻辑,以在实例化代理时利用Objenesis(而不是不需要 args 构造函数的CGLIB)。不幸的是,此功能没有记录,但我可以确认它适用于我的情况。