No qualifying bean of type ‘java.lang.String‘ available: expected at least 1 bean which qualifies

一、问题和详细异常

今天一个同事在开发时给一个类(AClassImpl)加了@AllArgsConstructor,希望通过private final XxClass xxClass的方式将XxClass注入到当前类:

@Service
@AllArgsConstructor
public class AClassImpl implements AClass {
    
    

    private final XsClass xxClass;

运行时报错如下:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'io.xxx.class' defined in URL [jar:file:/app/app.jar!/BOOT-INF/lib/xxx-SNAPSHOT.jar!xxxxx.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {
    
    }
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1206)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:571)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:923)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298)
	at io.xxx.Application.main(Application.java:17)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {
    
    }
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1777)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1333)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1287)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
	... 28 common frames omitted

二、原因分析

从报错提示可以看出是没有找到NoSuchBeanDefinition;根本原因是因为springioc容器加载bean默认使用无参构造进行初始化。

三、解决方案

给AClassImpl提供一个默认的构造方法。使用@RequiredArgsConstructor注解来替换@AllArgsConstructor注解;

@RequiredArgsConstructor 和 @AllArgsConstructor的区别?

  • @RequiredArgsConstructor会将类的每一个final字段或者non-null字段生成一个构造方法
  • @AllArgsConstructor 生成一个包含所有字段的构造方法;
  • @NoArgsConstructor 生成无参的构造方法;

使用@RequiredArgsConstructor可以代替@Autowrited注解;而@RequiredArgsConstructor是根据构造器注入的,所以会有循坏依赖的问题。

@RequiredArgsConstructor循环依赖问题解决措施

有三种方式可以解决:

  1. 改为使用@Autowired注解做属性方法注入Bean;
    不过,Spring 从 4.0 开始, 就不推荐使用属性注入模式了,原因在于它可以让我们忽略掉一些代码可能变坏的隐患。
  2. 使用@RequiredArgsConstructor(onConstructor =@_(@Autowired) ),这样默认都是通过@Autowired注入Bean的;
  3. 使用@RequiredArgsConstructor(onConstructor_={@Lazy} ),做懒加载处理。

猜你喜欢

转载自blog.csdn.net/Saintmm/article/details/125941552