所有分类
  • 所有分类
  • 未分类

Spring–解决注入实现类导致的启动失败问题

简介

说明

本文介绍SpringBoot注入实现类导致的启动失败的解决方案。

问题描述

  • 注册bean时,返回值类型是接口,方法里创建了一个实现类。
  • 通过@Autowired注入实现类,结果报错了,应用启动失败。
  • 通过@Autowired注入接口,启动成功。
  • 通过@Autowired注入接口,通过@Autowired注入实现类,启动成功。

问题复现

注入实现类启动失败

package com.knife.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class DemoApplication {
    @Autowired
    private DistributeLock distributeLock;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

@Configuration
class LockConfig{
    @Bean
    public Lock lock() {
        return new DistributeLock();
    }
}

interface Lock{}

class DistributeLock implements Lock{}

报错信息(无法找到com.knife.DistributeLock这个bean)

2022-09-10 16:37:43.419  INFO 142692 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1013 ms
2022-09-10 16:41:28.518  WARN 142692 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'distributeLock'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.knife.DistributeLock' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2022-09-10 16:41:28.521  INFO 142692 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2022-09-10 16:41:28.533  INFO 142692 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-09-10 16:41:28.601 ERROR 142692 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field distributeLock in com.knife.DemoApplication required a bean of type 'com.knife.DistributeLock' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.knife.DistributeLock' in your configuration.

2022-09-10 16:41:28.607  WARN 142692 --- [           main] o.s.boot.SpringApplication               : Unable to close ApplicationContext

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'springApplicationAdminRegistrar' defined in class path resource [org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.class]: Unsatisfied dependency expressed through method 'springApplicationAdminRegistrar' parameter 1; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.core.env.Environment' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:539) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.beans.

注入接口启动成功

package com.knife.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class DemoApplication {
    @Autowired
    private Lock lock;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

@Configuration
class LockConfig{
    @Bean
    public Lock lock() {
        return new DistributeLock();
    }
}

interface Lock{}

class DistributeLock implements Lock{}

结果(启动成功) 

注入接口和实现类启动成功

package com.knife.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class DemoApplication {
    @Autowired
    private Lock lock;

    @Autowired
    private DistributeLock distributeLock;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

@Configuration
class LockConfig{
    @Bean
    public Lock lock() {
        return new DistributeLock();
    }
}

interface Lock{}

class DistributeLock implements Lock{}

原因分析

报错原因概述

Spring是通过类型来匹配bean的,DemoApplication需要的是DistributeLock类型的bean,但找不到(只有Lock类型的bean),于是报错。

源码追踪

待补充。

解决方案

在注册Bean时,返回值类型与实际创建的类型必须是同一个,不能返回一个接口!

package com.knife.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class DemoApplication {
    @Autowired
    private DistributeLock lock;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

@Configuration
class LockConfig{
    @Bean
    public DistributeLock distributeLock() {
        return new DistributeLock();
    }
}

interface Lock{}

class DistributeLock implements Lock{}
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录