Суперкласс не имеет нулевых конструкторов, но аргументы не были переданы

Я использую 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. Однако, когда я применяю его к одному из моих других контроллеров, подобному этому,

@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? Я гуглил, но не могу найти никакого решения для этого.


person nilsi    schedule 05.03.2013    source источник
comment
Работает ли это, если вы используете инъекцию на основе свойств?   -  person Maksym Demidas    schedule 05.03.2013
comment
Вау, это сработало! если вы поставите это как ответ, я отмечу это как правильное. Я просто удалил конструктор и изменил его на это: @Inject private Facebook facebook; Протестировал это раньше, но не смог заставить его работать, потому что переменная изначально была окончательной. (Был окончательным в примере кода Springs, из которого я его получил).   -  person nilsi    schedule 05.03.2013


Ответы (3)


У CGlib есть одно важное ограничение: целевой класс должен предоставлять конструктор по умолчанию.

Если вы используете внедрение на основе свойств вместо внедрения на основе конструктора, проблема исчезнет.

person Maksym Demidas    schedule 05.03.2013
comment
Расширение этого ответа: это сработало бы нормально с помощью внедрения конструктора (что предпочтительнее), если бы вы не добавили @Transactional в контроллер. Как только вы добавите @Transactional, сработает АОП, и необходимо будет создать прокси. CGLib нужен конструктор по умолчанию. Другое решение — настроить транзакции Spring для использования AspectJ вместо прокси. Это требует немного большей настройки, но позволит транзакции в классе без конструктора по умолчанию. - person Craig Walls; 06.03.2013
comment
Это очень хороший комментарий! Я думаю, что это следует добавить к ответу. - person Ido.Co; 16.01.2014
comment
До Spring 4 прокси-классы на основе CGLIB требовали конструктора по умолчанию. И это не ограничение библиотеки CGLIB, а самого Spring. К счастью, с Spring 4 это больше не проблема. Прокси-классы на основе CGLIB больше не требуют конструктора по умолчанию. См. эту статью: blog.codeleak.pl/2014/07/ - person Rafal Borowiec; 02.07.2014
comment
Я нашел способ заставить его работать с внедрением конструктора и @Transactional. Создайте интерфейс, который реализует SearchController, и измените конструктор HomeController, чтобы он вместо этого брал экземпляр этого интерфейса. - person marstran; 12.01.2016
comment
В основном заставьте HomeController зависеть от интерфейса, а не от реализации. - person marstran; 12.01.2016
comment
Этот совет интерфейса действительно стоит мяты, должен быть ответом! - person Sebastian; 04.04.2016
comment
Комментарий от @marstran полезен тем, что позволяет одновременно использовать как инъекцию конструктора, так и @Transactional. Просто создайте класс с @Transactional для реализации интерфейса. - person Igor Rodriguez; 05.07.2017
comment
Я действительно не помню, чтобы делал этот комментарий, и я нахожу его немного запутанным. Почему я сказал, что HomeController должен принимать SearchController в качестве аргумента? Кто-нибудь может расшифровать, что я имел в виду? :) - person marstran; 05.07.2017
comment
@CraigWalls - Как вы предлагаете внедрить конструктор с помощью cglib? - person AlikElzin-kilaka; 14.03.2018

Я только что создал пустой конструктор по умолчанию, чтобы справиться с этим.

person Smart Coder    schedule 02.03.2016

Если вы используете в своем коде Lombok, вы можете просто добавить следующую аннотацию, чтобы избавиться от этой ошибки:

@NoArgsConstructor
public class SearchController {
person Navigatron    schedule 15.08.2018
comment
Серьезно чувак? Вы действительно считаете, что написание пустого конструктора — это большое дело, требующее дополнительной библиотеки и плагина IDE? - person sergpank; 04.12.2018
comment
@sergpank Если он уже включен в ваш проект, почему бы вам его не использовать? Я четко указал, используете ли вы Ломбок. Кстати, он может сделать гораздо больше, чем просто добавить пустой конструктор. - person Navigatron; 04.12.2018
comment
Спасибо за ваше мнение. Мне жаль, что ты так себя чувствуешь. - person Navigatron; 06.12.2018