Spring Boot 使用构造函数创建并自动连接组件

k97glaaz  于 2022-11-29  发布在  Spring
关注(0)|答案(4)|浏览(110)

我有下面的课

@Component
public class MyBean {
    
     private int val1;
    
    

    public MyBean(int val1) {
        this.val1 = val1;
    }

    public int getVal1() {
        return val1;
    }

    public void setVal1(int val1) {
        this.val1 = val1;
    }
    
    
    
    
    
    

}

我想自动布线Mybean,如下所示

@Service
public class MyService
{
    @Autowire
    private MyBean myBean;
}

运行时出现以下错误
构造函数MyBean的参数0需要类型为'int'的Bean,但找不到该Bean。

9avjhtql

9avjhtql1#

有许多方法可以实现它,所有这些都会导致将MyBean的适当示例注入到IOC容器中。

*具有@Configuration注解处理器的Bean定义

指示类声明一个或多个@Bean方法,并且可以由Spring容器处理以生成Bean定义。

@Configuration
public class Configuration {
    
    @Bean
    MyBean beanName() {
        return new MyBean('some_value');
    }
    
}

*使用BeanFactory中的Bean感知接口,如InitializingBean

访问IOC容器本身的方法有很多种,直接通过fluent api,或者间接通过实现bean感知接口(如InitializingBean),特别是如果在创建bean示例后有一些操作,请使用this

@Configuration
public class Configuration implements InitializingBean
{

    @Bean
    public MyBean beanName() {
        return new MyBean('some_value');
    }

    @Override public void afterPropertiesSet() throws Exception
    {
    //some operations
    ...
    }
}

*使用IOC示例作为ConfigurableApplication上下文

如前所述,此解决方法是直接访问IOC容器,假设您需要singelton作用域,并且Bean的规范名称为MyBean

ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
beanFactory.registerSingleton(MyBean, new MyBean('some_value'));

*XMl based bean声明

在Spring3.0之前,XML是定义和配置bean的唯一方式,现在它已经不再使用了。

<bean class="{root_path}.Mybean">
    <property name="val1" value="some_value"/>
</bean>
lndjwyie

lndjwyie2#

当通过构造函数进行自动装配时,Spring将每个参数都视为一个bean。换句话说,正如跟踪所示:项目/上下文中没有可用的int类型的@Bean,因此无法生成MyBean
如果您需要MyBean以原始int初始化,则应该改用@Configuration类别中的@Bean注解,以便传递值。

@Configuration
public class MyConfiguration {

    @Bean
    public MyBean myBean() { // MyBean must not have @Component annotation
        return new MyBean(1);
    }
 
}

此外,如果该属性已经具有getter和setter,则可以将val1的类型更改为Integer,删除构造函数或不带参数地声明它,并在MyService中设置它的值。

@Component
public class MyBean {
    
    private Integer val1;

    public MyBean() {
        // Empty constructor, might be removed
    }

    public int getVal1() {
        return val1;
    }

    public void setVal1(int val1) {
        this.val1 = val1;
    }

}

@Service 
public class MyService { 

    @Autowired private MyBean myBean;

    /* This method is called AFTER the constructor and dependency injections */
    @PostConstruct
    public void initialize() {
        myBean.setVal1(1);
    }

}

然而,根据用例的不同,MyBean可以是一个POJO,如果你需要用一个原语值来创建它的话。毕竟,不是Spring项目中的每个类都需要是Bean

woobm2wo

woobm2wo3#

我认为您的错误是因为spring告诉您它不知道使用哪个整数值来示例化Bean MyBean。您可以执行以下操作:

**a)**直接在Bean中设置默认值并使用无参数构造函数:

@Component
public class MyBean {
    
    private int val1 = 1; // or...
    private int val1; // default initialisation to 0

    public MyBean() {}
    ...
}

**b)**为MyBean提供不带参数的默认构造函数,并将值作为属性文件中的属性注入:

@Component
public class MyBean {
    
    @Value("${my.property.name}")
    private int val1;

    public MyBean() {}
    
    public MyBean(int val1) {
        this.val1 = val1;
    }
    ...
}

然后,在根资源目录中,需要有一个属性文件:

src/main/resource/application.properties

内容为:

my.property.name=1

阅读本文中有关属性的详细信息:https://www.baeldung.com/properties-with-spring

**c)**可能有很多其他的选项...这些将取决于你的具体用例。我们对你的类和哪些int值是合适的还不够了解。

brjng4g3

brjng4g34#

无参数构造函数

您可以在MyBean类中引入一个 no-args 默认构造函数,Spring将使用它,并且val1将具有一个0值(因为它是int类型的默认值)。

@豆

或者,您可以在配置类中创建一个用@Bean注解的方法,并通过它提供一个MyBean的示例,该示例具有您需要的任何val1值。

请注意,如果选择此选项,则需要MyBean类中删除@Component注解。

  • 范例:*
@Configuration
public class MyConfig {
    
    @Bean
    MyBean myBean() {
        return new MyBean(1_000);
    }
}

定义多个相同类型的Bean

另外,请注意使用@Bean,您可以根据需要定义任意多的MyBean风格。另一个优点是MyBean不一定是您的域类(它可以来自第三方库或JDK),而原型注解只能放在您的自定义类之上。
下面是一个例子:

@Configuration
public class BeanConfig {
    
    @Bean
    @Qualifier("1000")
    MyBean myBean1() {
        return new MyBean(1_000);
    }
    
    @Bean
    @Qualifier("8000")
    MyBean myBean2() {
        return new MyBean(8_000);
    }
}

需要使用@Qualifier注解来区分这些bean。它允许在应用程序的不同部分使用bean的不同风格。
让我们在服务中使用值为8000的bean:

@Service
public class MyService {
    private MyBean myBean; // field injection is a not a good practice
    
    public MyService(@Qualifier("8000") MyBean myBean) {
        System.out.println(myBean); // would allow to ditermin which bean is used here (don't forget to override toString)
        this.myBean = myBean;
    }
}

注意不建议在字段上使用@Autowired。常用的方法是使用构造函数注入,如果类中只有一个构造函数,则不需要使用@Autowired

相关问题