超类没有空构造函数,但没有给出参数

Posted

技术标签:

【中文标题】超类没有空构造函数,但没有给出参数【英文标题】:Superclass has no null constructors but no arguments were given 【发布时间】:2013-02-19 19:47:03 【问题描述】:

我在我的应用程序中使用 Spring Social:

<spring.framework.version>3.2.0.RELEASE</spring.framework.version>
<hibernate.version>4.1.9.Final</hibernate.version>
<commons-dbcp.version>1.4</commons-dbcp.version>
<org.springframework.social-version>1.1.0.BUILD-SNAPSHOT</org.springframework.social-version>
<org.springframework.social.facebook-version>1.1.0.BUILD-SNAPSHOT</org.springframework.social.facebook-version>
<org.springframework-version>3.2.1.RELEASE</org.springframework-version>
<org.springframework.security.crypto-version>3.1.3.RELEASE</org.springframework.security.crypto-version>

当我申请时

private final Facebook facebook;

@Inject
public SearchController(Facebook facebook) 
    this.facebook = facebook;

到我的 HomeController:

@Controller
public class HomeController 


    private final Facebook facebook;

    @Inject
    public HomeController(Facebook facebook) 
        this.facebook = facebook;
    

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Model model) 
        return "home";
    


注入工作正常,我可以从facebook 获取信息。但是,当我将它应用到我的其他 Cotroller 之一时,像这样的一个

@Controller
@Transactional
@RequestMapping(value = "/search")
public class SearchController 

    private static final Logger logger = LoggerFactory.getLogger(SearchController.class);

    private final Facebook facebook;

    @Inject
    public SearchController(Facebook facebook) 
        this.facebook = facebook;
    

    @PersistenceContext
    private EntityManager entityManager;

    ...

我收到此错误:

mar 05, 2013 12:46:36 EM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/project] threw exception [Request processing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchController' defined in file [C:\Users\Nilsi\Downloads\springsource\vfabric-tc-server-developer-2.7.2.RELEASE\base-instance\wtpwebapps\course_info\WEB-INF\classes\com\courseinfo\project\controller\SearchController.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.courseinfo.project.controller.SearchController]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given] with root cause
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
    at org.springframework.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721)
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:111)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:412)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1492)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1117)
    at org.springframework.web.method.HandlerMethod.createWithResolvedBean(HandlerMethod.java:202)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:233)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:55)
    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:297)
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1091)
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1076)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:896)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

我的猜测是我不能将 facebook 注入带有注释 @Transactional 的控制器?

【问题讨论】:

如果您使用基于属性的注入,它是否有效? 哇,成功了!如果您将其作为答案,我会将其标记为正确。我只是删除了构造函数并更改为:@Inject private Facebook facebook;之前测试过但无法使其工作,因为变量最初是最终的。 (在我从中获得的 Springs 示例代码中是最终的)。 【参考方案1】:

CGlib 有一个重要限制:目标类必须提供默认构造函数。

如果你使用基于属性的注入而不是基于构造函数的注入,问题就会消失。

【讨论】:

扩展这个答案:如果您没有将@Transactional 添加到控制器,那么通过构造函数注入(这是首选)可以正常工作。一旦你添加了@Transactional,AOP 就会启动并且必须创建一个代理。 CGLib 需要一个默认构造函数。另一种解决方案是将 Spring 事务配置为使用 AspectJ 而不是代理。这需要更多设置,但允许在没有默认构造函数的类上进行事务。 这是一个非常好的评论!我认为应该将其添加到答案中。 在 Spring 4 之前,基于 CGLIB 的代理类需要默认构造函数。这不是CGLIB库的限制,而是Spring本身。幸运的是,从 Spring 4 开始,这不再是问题。基于 CGLIB 的代理类不再需要默认构造函数。见这篇文章:blog.codeleak.pl/2014/07/… 我找到了一种方法让它与构造函数注入和@Transactional一起工作。创建一个SearchController 实现的接口,并将HomeController 的构造函数更改为采用该接口的实例。 基本上使HomeController 依赖于一个接口,而不是一个实现。【参考方案2】:

我刚刚创建了一个空的默认构造函数来处理这个问题。

【讨论】:

【参考方案3】:

如果您在代码中使用Lombok,则只需添加以下注释即可消除此错误:

@NoArgsConstructor
public class SearchController 

【讨论】:

说真的老兄?你真的认为编写一个空的构造函数是一件大事,需要额外的库和 IDE 插件吗? @sergpank 如果它已经包含在您的项目中,您为什么不使用它?我明确表示“如果您使用的是 Lombok”。它可以做的不仅仅是顺便添加一个空的构造函数。 感谢您的意见。很抱歉你有这种感觉。 @NoArgsConstructor 是我今天讨厌 Lombok 的原因之一。它提供了可忽略不计的代码长度减少,同时阻止我使用我的 IDE 的“查找用法”选项。只需编写构造函数并记录它存在的原因(请参阅您未能记录为什么需要注释)。 @Torben 这个问题出在您的 IDE 上,在 Eclipse 中使用“打开调用层次结构”会正确报告所有用法。您可能可以更改一个设置以使其在您使用的任何 IDE 中工作。

以上是关于超类没有空构造函数,但没有给出参数的主要内容,如果未能解决你的问题,请参考以下文章

ObjectInputStream - 读取对象 - 有没有办法阻止调用无参数超类构造函数?

使用 CDI 而不是 @ManagedBean: UnproxyableResolutionException 因为超类没有无参数构造函数

Java 构造函数 - 子类构造函数中的可选参数

=default 和没有参数的空构造函数之间的区别? [复制]

有没有在 C++ 中不调用超类的构造函数的时候?

MassTransit.QuartzIntegration.ScheduledMessageJob:无法实例化没有空构造函数的类型(参数'ScheduledMessageJob')'