Spring Boot 构造函数自动装配异常

     2023-02-19     120

关键词:

【中文标题】Spring Boot 构造函数自动装配异常【英文标题】:Spring boot Constructor Autowired Exception 【发布时间】:2016-09-04 03:49:51 【问题描述】:

我的 spring boot 应用程序中有这些类(spring hibernate/data/jpa/web):

pkg 实体:

public interface Base 
// getter/setter methods


@MappedSuperclass
public abstract class AbsBase implements Base 
// common fields & getter/setter methods


@Entity(name = "Config")
@Table(name = "config")
public class Config extends AbsBase implements Base, Serializable 
  //additional fields & getter/setter methods

pkg 存储库:

@NoRepositoryBean
public interface BaseRepository<T extends Base> extends JpaRepository<T, Integer> 

@Repository
public interface ConfigRepository extends BaseRepository<Config> 
//Queries

pkg 服务:

@Transactional
public interface BaseService<T extends Base> 

    @Transactional  void add(T obj);
    @Transactional  void edit(T obj);
    //Etc..


public abstract class AbsBaseService<T extends Base> implements BaseService<T> 

    private BaseRepository<T> repository;

    public AbsBaseService(BaseRepository<T> repository) 
        super();
        this.repository = repository;
    

    @Override   public void add(T obj)  repository.save(obj); 
    @Override   public void edit(T obj)  repository.save(obj); 
    // Etc


@Service
public class ConfigService extends AbsBaseService<Config> implements BaseService<Config> 

    private ConfigRepository repository;

    @Autowired
    public ConfigService(ConfigRepository repository) 
        super(repository);
        this.repository = repository;
    
    // Etc.

如果我不创建任何控制器所有工作,但如果我创建一个控制器:

pkg 控制器:

public interface BaseController<T extends Base>  // methods 

public abstract class AbsBaseController<T extends Base> implements BaseController<T> 

    private BaseService<T> service;

    public AbsBaseController(BaseService<T> service) 
        this.service = service;
    

@Override
@RequestMapping(value = "/Add", method = RequestMethod.POST)
public String addAction(@ModelAttribute("entity") T entity, BindingResult result, Model model,
        final RedirectAttributes redirectAttributes) 

    service.add(entity, result);
    if (result.hasErrors()) 
        return addUrl;
    


@Controller
public class ConfigController extends AbsBaseController<Config> implements BaseController<Config> 

    private ConfigService configService;

    @Autowired
    public ConfigController(ConfigService configService) 
        super(configService);
        this.configService = configService;
    

我收到此错误(在 ConfigController 中出现错误 autowired ConfigService):

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'configControllerImpl' defined in file [C:\workspace-sts\prueba_boot_thymeleaf\target\classes\prueba\controller\config\ConfigControllerImpl.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [prueba.service.config.ConfigServiceImpl]: No qualifying bean of type [prueba.service.config.ConfigServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: ; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [prueba.service.config.ConfigServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.3.RELEASE.jar:1.3.3.RELEASE]
    at prueba.BootThymeleafApplication.main(BootThymeleafApplication.java:12) [classes/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [prueba.service.config.ConfigServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 19 common frames omitted

第一个问题是: 我已经注释了@Transaction BaseService 接口及其方法。这是正确的?在 AbsBaseService 类中更好?

我看到 configService 构造函数在异常之前执行。 为什么不自动接线?


更新

我需要构造函数@Autowired,因为我在抽象/超类通用服务/控制器中实现了常用方法。

继承树: AbsBaseXXXX --> AbsBaseCodeNameXXXX --> AbsBaseCodeNamePeriodXXXX

Config 从 AbsBase 扩展并实现 Base。 ConfigService 从 AbsBaseService 扩展并实现 BaseService(使用 ConfigRepository) ConfigController 从 AbsBaseController 扩展并实现 BaseController(使用 ConfigService)

我有一个通用方法实现的通用抽象类: 实体接口: Base、BaseCodeName、BaseCodeNamePeriod....

抽象通用实体类: AbsBase、AbsBaseCodeName、AbsBaseCodeNamePeriod....

通用接口: BaseRepository、BaseCodeNameRepository、BaseCodeNamePeriodRepository、...

抽象通用服务(他们需要相应的通用存储库): AbsBaseService, AbsBaseCodeNameService,AbsBaseCodeNamePeriodService,...

抽象的通用控制器(他们需要相应的通用服务): AbsBaseController 等...

【问题讨论】:

你在哪里启动 Spring boot(包)的类,你的控制器和服务在哪里?也许根本没有扫描 Service bean 代码:drive.google.com/open?id=0B4DUWMYsjWtdVVRibDFZOVhac2s 【参考方案1】:

首先,你们中的大多数代码都可以简化,至少可以测试它是否运行良好:

@Transactional
public interface BaseService<T extends Base> 

    void add(T obj); // No need to repeat @Transactional here, unless you want to override default behaviour (says, read_only, for instance)
    void edit(T obj);
    //Etc..


// Not much use of an Abstract class here, all methods are exposed in the interface already

@Service
public class ConfigService implements BaseService<Config> 

    // Autowire the field directly. Constructor not needed anymore in this case
    @Autowired
    private ConfigRepository repository;
    // Etc.

控制器将遵循与服务相同的准则。

现在应该可以正常工作了。如果没有,您需要使用完整的堆栈跟踪更新您的问题(或者至少是最后一个 caused by 块,这是真正有意义的块)。

【讨论】:

在抽象类(服务和控制器)中,我实现了来自另一个服务/控制器类(如 Config)的常用方法。 好的,这并没有改变太多的解决方案,只是增加了清晰度(更短的代码:))。这里的重点是将@Autowired注解放在属性本身 你测试了吗?这可能有助于解决问题 现在,如果我没有控制器它可以工作,但如果我使用属性 @Autowired 不起作用(我会花更多时间)。 你能压缩你的应用程序,然后发布链接吗?您发布的代码似乎没问题,因此线索可能在其他地方【参考方案2】:

解决办法:

创建服务接口: IConfigService 扩展 BaseService

更改服务类: ConfigService 扩展 AbsBaseService 实现 IConfigService

在 ControllerConfig 中将 ConfigService 替换为 IConfigService

如果我使用接口工作,但如果我使用类不工作。我不明白为什么,但它有效。

【讨论】:

【参考方案3】:

根据https://drive.google.com/open?id=0B4DUWMYsjWtdVVRibDFZOVhac2s 上发布的代码,我现在很清楚您想要实现的目标。

您想创建一个层次结构的类(例如服务),在每个层次上定义一些功能。例如:

RepoA 定义了一个 methodA 方法。 RepoB 扩展 RepoA 和 定义了一个methodB 方法。 ServiceA 使用 RepoA 类 公开这个方法 ServiceB 扩展 ServiceA 并暴露其 方法和ServiceA 方法 等等……

调试您的应用程序时,我发现 Spring 在调用此代码时会尝试创建一个新的 AccountService bean,而不是使用现有的:

@Controller
@RequestMapping("/Account")
public class AccountController extends AbsBaseDataController<Account> 

    private AccountService service;

    @Autowired
    public AccountController(AccountService service) 
        super(service);
        this.service = service;
        System.out.println("AccountController-CONSTRUCTOR");
    

这是因为您直接使用AccountService 类,而不是接口。这在这里很重要,因为 Spring 在您的类周围创建了一个代理,以便能够在它们上使用 AOP。所以当涉及到自动装配时,类不匹配(你认为你的类的一个实例被注入了,但这实际上是一个com.sun.proxy.Proxy)。

由于这些 Java 代理实现了您的类的接口,您应该为您的 AccountService(比如 IAccountService)创建一个接口,并在您的 AccountController 类的构造函数中使用它而不是原始的 AccountService 类:

界面

public interface IAccountService extends BaseDataService<Account> 

控制器

@Controller
@RequestMapping("/Account")
public class AccountController extends AbsBaseDataController<Account> 

    private IAccountService service;

    @Autowired
    public AccountController(IAccountService service) 
        super(service);
        this.service = service;
        System.out.println("AccountController-CONSTRUCTOR");
    

服务类

@Service
public class AccountService extends AbsBaseDataService<Account> implements IAccountService 
[...]

【讨论】:

谢谢。我在我的解决方案中创建了一个层次结构接口,它可以工作,但我不知道为什么可以使用接口,为什么不能使用类...我需要学习 AOP。 我在上面的回答中(相当快地)解释了这一点。你需要澄清吗? AOP 允许您“围绕”您的方法调用(即在您的调用之前和之后)做一些事情。为了做到这一点,你的类需要被代理,所以这些调用可以被执行 好的 :) 如果您认为它可以解决您的问题,请接受该答案。谢谢!

spring3.2注释自动装配多个构造函数(代码片段)

Spring文档:每个类只能标记一个带注释的构造函数,但可以注释多个非必需的构造函数。如果我有一个自动装配的构造函数,一切都很好。如果我有两个或更多autowired,但required=false注释构造函数,一切都很好。但是如果我以某... 查看详情

spring(代码片段)

文章目录SpringBeans自动装配Spring自动装配的局限性Spring自动装配byNameSpring自动装配byName样例Spring自动装配byTypeSpring自动装配byType样例Spring由构造函数自动装配Spring由构造函数自动装配SpringBeans自动装配可以使用·bean元素来声明bean... 查看详情

使用构造函数自动装配泛型类型 [Spring 4.2.5]

】使用构造函数自动装配泛型类型[Spring4.2.5]【英文标题】:Autowiringgenerictypeswithconstructor[Spring4.2.5]【发布时间】:2016-08-1703:11:57【问题描述】:我是Spring新手,正在尝试像本文http://www.ibm.com/developerworks/library/j-genericdao/中那样实... 查看详情

spring入门(代码片段)

文章目录SpringBeans自动装配Spring自动装配的局限性Spring自动装配byNameSpring自动装配byName样例Spring自动装配byTypeSpring自动装配byType样例Spring由构造函数自动装配Spring由构造函数自动装配SpringBeans自动装配可以使用·bean元素来声明bean... 查看详情

在spring中通过构造自动装配--constructor

在Spring中,可以使用“通过构造自动装配”,实际上是按构造函数的参数类型自动装配。 这意味着,如果一个bean的数据类型与其他bean的构造器参数的数据类型是相同的,那么将自动装配。 packageauto_constructor;/***Createdbyluo... 查看详情

如何在Spring bean中传递类构造函数参数由注释自动装配

】如何在Springbean中传递类构造函数参数由注释自动装配【英文标题】:HowtopassclassconstructorparametersinSpringbeanAutowiredbyannotations【发布时间】:2015-02-2000:19:24【问题描述】:没有IOC容器的正常方法是:newUser("Names",22);这里的参数值是... 查看详情

spring4-自动装配beans-通过构造函数参数的数据类型按属性自动装配bean

1.创建Maven项目,项目名称springdemo17,如图所示650)this.width=650;"src="https://s1.51cto.com/wyfs02/M01/8F/15/wKiom1jTN5mwr-2zAAAVZbvPl7I842.png-wh_500x0-wm_3-wmp_4-s_3468380499.png"title="QQ截图20170323104810.png"al 查看详情

ServiceImpl 构造函数中的 Spring Boot WebClient Builder 初始化

】ServiceImpl构造函数中的SpringBootWebClientBuilder初始化【英文标题】:SpringBootWebClientBuilderinitializationinServiceImplConstructor【发布时间】:2021-02-1203:31:33【问题描述】:我正在尝试遵循使用WebClientBuilder自动装配Webclient的最佳实践,但有... 查看详情

Spring Boot 单元测试自动装配

】SpringBoot单元测试自动装配【英文标题】:SpringBootUnitTestAutowired【发布时间】:2016-03-2922:43:14【问题描述】:我有以下课程:ApplicationAndConfiguration类packagemypackage.service;importmypackage.service.util.MyUtility;importorg.springframework.boot.Sprin 查看详情

使用服务的spring安全性不会自动赋予依赖关系并提供空指针异常

我的UserService出现问题。它无法识别其中定义的自动连接依赖项。我尝试直接在变量和构造函数上使用Autowired注释。knowledgbaseDao在loadUserByUsername中无效。在启动时,此类的构造函数被调用3次。每个创建不同的对象。第一个是使用... 查看详情

静态字段的 Spring Boot 自动装配 BeanCreationException

】静态字段的SpringBoot自动装配BeanCreationException【英文标题】:SpringbootautowiringBeanCreationExceptionforstaticfield【发布时间】:2018-12-1921:22:31【问题描述】:我在自动装配属性类时遇到问题。以下是我的属性类,当我在@service类中自动... 查看详情

spring学习-----spring使用@autowired注解自动装配

Spring使用@Autowired注解自动装配在上一篇Spring学习(三)-----Spring自动装配Beans示例中,它会匹配当前Spring容器任何bean的属性自动装配。在大多数情况下,你可能只需要在特定的 bean 自动装配属性。在Spring中,可以使用 @Auto... 查看详情

在 Spring Boot 应用程序中自动装配 ObjectMapper

】在SpringBoot应用程序中自动装配ObjectMapper【英文标题】:AutowireObjectMapperinSpringbootapplication【发布时间】:2018-07-2809:41:54【问题描述】:我需要在我的Spring-boot应用程序中使用默认的ObjectMapper作为单例实例。我可以在我的应用程... 查看详情

spring boot:如何配置自动装配的 WebTestClient

】springboot:如何配置自动装配的WebTestClient【英文标题】:springboot:howtoconfigureautowiredWebTestClient【发布时间】:2019-10-2116:09:18【问题描述】:SpringBoot中是否有任何属性可用于配置@AutowiredWebTestClient?例如,如何在WebTestClient上设置s... 查看详情

spring学习总结——高级装配学习一(处理自动装配的歧义性)

  我们已经看到如何使用自动装配让Spring完全负责将bean引用注入到构造参数和属性中。自动装配能够提供很大的帮助。不过,spring容器中仅有一个bean匹配所需的结果时,自动装配才是有效的。如果不仅有一个bean能够匹配结果... 查看详情

spring属性依赖注入

...:构造方法、setter方法基于注解装配:自动装配:struts和spring整合可以自动装配byType:按类型装配byName:按名称装配constructor:构造装配,auto:不确定装配。 一.构造方法注入User.javapublicclas 查看详情

Spring Boot 测试不会自动装配所有依赖项

】SpringBoot测试不会自动装配所有依赖项【英文标题】:Springboottestdoesn\'tAutowirealldependencies【发布时间】:2021-10-1906:43:24【问题描述】:我的测试场景中有一些令人困惑的错误。我们想重构一个根本没有经过测试的应用程序。为... 查看详情

如何在 Spring Boot 中自动装配 Hibernate SessionFactory

】如何在SpringBoot中自动装配HibernateSessionFactory【英文标题】:HowtoautowireHibernateSessionFactoryinSpringboot【发布时间】:2017-10-0906:56:27【问题描述】:我已经创建了一个SpringBoot应用程序,我想处理HibernateSessionFactory,所以在我的服务类... 查看详情