[SpringBoot]: 简单组件无法自动装配 String 类

huangapple go评论70阅读模式
英文:

[SpringBoot]: Simple component cannot autowire String class

问题

我有这个简单的组件类:

package jason;

import org.springframework.stereotype.Component;

@Component
public class Messenger {
    private String message;

    public Messenger(String message) {
        this.message = message;
    }

    public void setMessage(String message){
        this.message  = message;
    }

    public void getMessage(){
        System.out.println("Your Message : " + message);
    }
}

在构造函数的参数中,IntelliJ 报告:Could not autowire. No beans of 'String' type found.

在这个小玩具项目中还有另外两个类:Config

package jason;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackageClasses = Messenger.class)
public class Config {
    @Bean
    public Messenger helloWorld(){
        return new Messenger("Hello World!");
    }
}

MainApp

package jason;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        Messenger obj = context.getBean("helloWorld", Messenger.class);
        obj.getMessage();
    }
}

奇怪的是,除了看似在编译时出现的错误外,项目会构建成功,但在运行时会失败,显示以下错误:

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'messenger' defined in file [C:\Users\jasonfil\code\green-taxi\target\classes\jason\Messenger.class]: Unsatisfied dependency expressed through constructor parameter 0; 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: {}

我在这里做错了什么?我对 SpringBoot 还不熟悉。可能有 IoC(控制反转)的误解。

英文:

I have this simple component class:

package jason;

import org.springframework.stereotype.Component;

@Component
public class Messenger {
    private String message;


    public Messenger(String message) {
        this.message = message;
    }

    public void setMessage(String message){
        this.message  = message;
    }

    public void getMessage(){
        System.out.println("Your Message : " + message);
    }
}

In the argument for the constructor, IntelliJ reports: Could not autowire. No beans of 'String' type found.

There are two more classes in this small toy project: Config:

package jason;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackageClasses = Messenger.class)
public class Config {
    @Bean
    public Messenger helloWorld(){
        return new Messenger("Hello World!");
    }
}

and MainApp:

package jason;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        Messenger obj = context.getBean("helloWorld", Messenger.class);
        obj.getMessage();
    }
}

Curiously, besides the seemingly compile-time error, the project builds, but fails at runtime with:

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'messenger' defined in file [C:\Users\jasonfil\code\green-taxi\target\classes\jason\Messenger.class]: Unsatisfied dependency expressed through constructor parameter 0; 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: {}

What am I doing wrong here? New to SpringBoot. Might have IOC misconception(s).

答案1

得分: 2

你正在混合使用Messenger类的两种依赖注入方式,一种是基于注解的依赖注入,使用@Component,另一种是将其声明为一个bean,使用@Bean在配置类中。

当你尝试使用AnnotationConfigApplicationContext进行Messenger的注入,并且启用了组件扫描时,Spring会首先使用基于注解的注入,即@Component

因此,Spring将调用默认构造函数来注入你的bean,当然,如果没有基于构造函数的自动装配(这是你的情况),所以你需要为Messenger添加默认构造函数。如果没有默认构造函数,Spring将使用可用的构造函数,因此会出现上述错误。当然,你需要删除@Bean配置,因为你没有在使用它:

package jason;

import org.springframework.stereotype.Component;

@Component
public class Messenger {

    private String message;

    public Messenger() {
    }

    public Messenger(String message) {
        this.message = message;
    }

    public void setMessage(String message){
        this.message  = message;
    }

    public void getMessage(){
        System.out.println("Your Message : " + message);
    }
}

或者,如果你想要使用bean配置,你可以从Messenger中移除@Component,并且移除@ComponentScan

package jason;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {
    @Bean
    public Messenger helloWorld(){
        return new Messenger("Hello World!");
    }
}
英文:

You are mixing two ways of bean injection with Messenger class, annotation-based injection with @Component, and you are declaring it as a bean, with @Bean, in the configuration class.

When you try to inject Messenger using the AnnotationConfigApplicationContext with an activated component scan, Spring will use the annotation-based injection first, so @Component.

So Spring will call the default constructor to inject your bean, of course, if there is no constructor based autowiring (that's your case), so you need to add the default constructor to Messenger. if there is no default constructor Spring will use the available constructor, so will get the error above. Of course, you need to delete the @Bean configuration because you are not using it:
package jason;

import org.springframework.stereotype.Component;

@Component
public class Messenger {

    private String message;

    public Messenger() {
    }

    public Messenger(String message) {
        this.message = message;
    }

    public void setMessage(String message){
        this.message  = message;
    }

    public void getMessage(){
        System.out.println("Your Message : " + message);
    }
}

Or, if you want to use the bean configuration, you can remove @Component from Messenger, and also remove @ComponentScan:

package jason;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {
    @Bean
    public Messenger helloWorld(){
        return new Messenger("Hello World!");
    }
}

答案2

得分: 1

你正在同时使用Java配置类型的Bean注册和组件扫描类型的Bean注册。

最快的解决方案是从Messenger类中移除@Component注解。

英文:

You are using Java Config type Bean registration as well as Component Scan type Bean registration.

the quickest solution is to remove @Component from the Messenger class.

huangapple
  • 本文由 发表于 2020年9月22日 03:28:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/63998795.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定