springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type ‘x‘ available

这篇具有很好参考价值的文章主要介绍了springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type ‘x‘ available。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 复现错误


今天在执行quartz定时任务时,报出如下错误:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxx.CollectionTaskServiceImpl' available
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1127)
	at com.xxx.SpringApplicationContext.getBean(SpringApplicationContext.java:19)
	at com.xxx.quartz.CollectionTaskJob.execute(CollectionTaskJob.java:27)
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
	... 1 common frames omitted

发现这个错误:No qualifying bean of type 'com.xxx.CollectionTaskServiceImpl' available

2. 分析错误


我们继续看错误,错误发生在SpringApplicationContext.getBean的方法中。

结合No qualifying bean of type 'com.xxx.CollectionTaskServiceImpl' available错误可知,SpringApplicationContext拿不到CollectionTaskServiceImpl这个类。

如是SpringApplicationContext的源码:

@Component
public class SpringApplicationContext implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringApplicationContext.applicationContext = applicationContext;
    }

    public static <T> T getBean(Class<T> requiredType){
        return applicationContext.getBean(requiredType);
    }
}

SpringApplicationContext实现了 ApplicationContextAware 接口,并由@Component注解。

我们再去往下看,错误在CollectionTaskJob类的execute方法中,如下代码:

@Slf4j
@DisallowConcurrentExecution
public class CollectionTaskJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        CollectionTaskServiceImpl collectionTaskServiceImpl = SpringApplicationContext.getBean(CollectionTaskServiceImpl.class);
        //此处省略逻辑代码
   }
}

我们再去看CollectionTaskServiceImpl类,如下代码所示:

@Service
public class CollectionTaskServiceImpl implements CollectionTaskService {
	//此处省略逻辑代码
}

CollectionTaskServiceImpl实现了CollectionTaskService接口,并由@Service注解。

按道理说,CollectionTaskServiceImpl类注入到spring容器中,通过SpringApplicationContext能够拿得到,但结果是拿不到的。

但为什么拿不到呢?我们需要写个测试类,如下代码所示:

@Component
public class Test implements CommandLineRunner, ApplicationContextAware {

  private ApplicationContext applicationContext;

  @Override
  public void run(String... args) throws Exception {
    Map<String, CollectionTaskServiceImpl> beansOfType =
        applicationContext.getBeansOfType(CollectionTaskServiceImpl.class);
    System.out.println();
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }
}

测试类Test实现了CommandLineRunnerApplicationContextAware接口,此时,我们运行代码:

no qualifying bean of type 'com.example.domain.rule.service.engine.impl.rule,免费专栏,1024程序员节,spring,spring boot,后端,java

你会清楚的看到,beansOfType的容器为0,确实没有拿到。

我们将CollectionTaskServiceImpl修改为CollectionTaskService

 @Override
  public void run(String... args) throws Exception {
    Map<String, CollectionTaskService> beansOfType =
        applicationContext.getBeansOfType(CollectionTaskService.class);
    System.out.println();
  }

重新运行:

no qualifying bean of type 'com.example.domain.rule.service.engine.impl.rule,免费专栏,1024程序员节,spring,spring boot,后端,java

此时,拿到了CollectionTaskServiceImpl的对象,但注意红框处,它采用的是jdk aop 的动态代理。

然后,我修改CollectionTaskServiceImpl类,不实现CollectionTaskService接口,如下代码所示:

@Service
public class CollectionTaskServiceImpl {
	//此处省略逻辑代码
}

run方法依然是CollectionTaskServiceImpl,如下代码所示:

@Override
  public void run(String... args) throws Exception {
    Map<String, CollectionTaskServiceImpl> beansOfType =
        applicationContext.getBeansOfType(CollectionTaskServiceImpl.class);
    System.out.println();
  }

重新运行代码:

no qualifying bean of type 'com.example.domain.rule.service.engine.impl.rule,免费专栏,1024程序员节,spring,spring boot,后端,java

如此,也能拿到了CollectionTaskServiceImpl的对象,但注意红框处,它采用的是spring cglib的动态代理。

分析到这里大体就明白了,可以有如下两种解决方法。

3. 解决问题

3.1 解决方法一


修改CollectionTaskJob类的execute方法,在SpringApplicationContext.getBean方法中传入CollectionTaskService.class接口,如下代码所示:

@Slf4j
@DisallowConcurrentExecution
public class CollectionTaskJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        CollectionTaskServiceImpl collectionTaskServiceImpl = (CollectionTaskServiceImpl) SpringApplicationContext.getBean(CollectionTaskService.class);
        //此处省略逻辑代码
   }
}

3.2 解决方法二


修改CollectionTaskServiceImpl类,不实现CollectionTaskService即可。

4. 分析spring中的jdk和cglib的动态代理

4.1 动态代理对比


JDK动态代理是实现了被代理对象所实现的接口,CGLib是继承了被代理对象。

JDKCGLib都是在运行期生成字节码,JDK是直接写Class字节码。CGLib使用ASM框架Class字节码,Cglib代理实现更复杂,生成代理类的效率比JDK代理低。

JDK调用代理方法,是通过反射机制调用,CGLib是通过FastClass机制直接调用方法,CGLib执行效率更高。

4.2 原理区别


java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。核心是实现InvocationHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知。

cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

核心是实现MethodInterceptor接口,使用intercept()方法进行面向切面的处理,调用相应的通知。

  1. 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
  2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
  3. 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

4.3 性能区别

  1. CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

  2. jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6jdk7CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理。

4.4 各自局限

  1. JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理。

  2. cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

类型 机制 回调方式 适用场景 效率
JDK动态代理 委托机制,代理类和目标类都实现了同样的接口,InvocationHandler持有目标类,代理类委托InvocationHandler去调用目标类的原始方法 反射 目标类是接口类 效率瓶颈在反射调用稍慢
CGLIB动态代理 继承机制,代理类继承了目标类并重写了目标方法,通过回调函数MethodInterceptor调用父类方法执行原始逻辑 通过FastClass方法索引调用 非接口类、非final类,非final方法 第一次调用因为要生成多个Class对象,比JDK方式慢。多次调用因为有方法索引比反射快,如果方法过多,switch case过多其效率还需测试

4.5 静态代理和动态的本质区别

  1. 静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步新增,违背开闭原则。

  2. 动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则。

  3. 若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成,无需修改代理类的代码。文章来源地址https://www.toymoban.com/news/detail-765908.html

到了这里,关于springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type ‘x‘ available的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 解决:No qualifying bean of type ‘org.springframework.web.client.RestTemplate‘ available:

    SpringBoot 项目启动时报错:  No qualifying bean of type \\\'org.springframework.web.client.RestTemplate\\\' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}     产生原因 :由于springboot版本问题,当前项目的版本需要

    2024年02月04日
    浏览(44)
  • No qualifying bean of type ‘org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate‘ a

    No qualifying bean of type ‘org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate’ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 提示找不到 ElasticsearchRestTemplate 写一个配置类注入

    2024年02月17日
    浏览(46)
  • 已解决org.springframework.beans.factory.UnsatisfiedDependencyException org.springframework.beans.factor

    已解决org.springframework.beans.factory.UnsatisfiedDependencyException org.springframework.beans.factory.异常的正确解决方法,亲测有效!!! org.springframework.beans.factory.UnsatisfiedDependencyException org.springframework.beans.factor 对于 org.springframework.beans.factory.UnsatisfiedDependencyException 异常,通常是由于依赖注

    2024年02月05日
    浏览(47)
  • exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException

    原因: Spring Boot异常org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有可用的合格Bean类型:预期匹配单个Bean,但是匹配到了多个,当该bean被自动装配时与Spring Boot应用程序上下文中的两个或多个加载的Bean匹配时,就会发现该异常。 Spring Boot允许从一个接口或抽象类创

    2024年02月09日
    浏览(43)
  • 【Spring常见错误】No qualifying bean of type

    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name \\\'com.ssmpdemo.ServiceTest\\\': Unsatisfied dependency expressed through field \\\'userService\\\'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type \\\'com.ssmpdemo.service.UserService\\\' available: expected at leas

    2023年04月08日
    浏览(43)
  • org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean (启动项目报错)

    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name \\\'shiroFilter\\\' defined in class path resource [com/cdzn/mhs/config/ShiroConfig.class]: Unsatisfied dependency expressed through method \\\'shiroFilter\\\' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with n

    2024年02月10日
    浏览(48)
  • org.springframework.beans.factory.BeanCreationException: Error creating bean with name

    异常日志:[WARNING] Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name \\\'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping\\\': Initialization of bean failed; nested exception is org.springframework.beans.fac

    2024年02月02日
    浏览(85)
  • 报错:Caused by org.springframework.beans.factory.BeanCreationException

    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘transactionManager’ defined in class path resource [spring/spring-service.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type ‘java.lang.String’ to

    2024年02月13日
    浏览(45)
  • Java No qualifying bean of type * available:expected at least * bean which qualifies as autowire问题解决

    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type \\\'com.xudongbase.user.dubbo.service.userDubboService\\\' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} 1、使用@AllArgsContructor注解进行自动装配时,默认是以@Autowired注解装配的,但是其中有一

    2024年02月07日
    浏览(34)
  • 异常:org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name

    出现这种异常主要是无法创建bean到容器中,主要有以下几种情况: 1.注解没有添加: controller: 注: controller类要加入@RestController注解,@AllArgsConstructor注解视情况而定。 引入了private final IEnterpriseService service,所以需要注入,可以在controller类上加入@AllArgsConstrctor注解修饰。

    2024年02月21日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包