了解配置文件中的主要注释

问题描述 投票:0回答:2

我正在尝试从此video了解@Profile中@Primary的行为

使用配置文件进行依赖注入。文件application.properties中的活动配置文件为english,运行该配置文件会显示错误

expected single matching bean but found 2: helloWorldServiceEnglish,helloWorldServiceSpanish

在helloConfig.java中添加@Primary批注解决了该错误:

    @Bean
    @Profile("english")
    @Primary
    public HelloWorldService helloWorldServiceEnglish(HelloWorldFactory factory) {
        return factory.createHelloWorldService("en");
    }

当我使用Profile自动装配时,只有一个名为english的Profile,那么为什么要搜索没有@Profile注释的其他bean?以及如何添加@Primary来改变这种行为?是否可以在不使用@primary的情况下运行此示例?

helloConfig.java

package com.spring.config;

import com.spring.services.HelloWorldFactory;
import com.spring.services.HelloWorldService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;

@Configuration
public class HelloConfig {

    @Bean
    public HelloWorldFactory helloWorldFactory() {
        return new HelloWorldFactory();
    }

    @Bean
    @Profile("english")
    @Primary
    public HelloWorldService helloWorldServiceEnglish(HelloWorldFactory factory) {
        return factory.createHelloWorldService("en");
    }

    @Bean
    @Qualifier("spanish")
    public HelloWorldService helloWorldServiceSpanish(HelloWorldFactory factory) {
        return factory.createHelloWorldService("es");
    }

    @Bean
    @Profile("french")
    public HelloWorldService helloWorldServiceFrench(HelloWorldFactory factory) {
        return factory.createHelloWorldService("fr");
    }

    @Bean
    @Profile("german")
    public HelloWorldService helloWorldServiceGerman(HelloWorldFactory factory) {
        return factory.createHelloWorldService("de");
    }

    @Bean
    @Profile("polish")
    public HelloWorldService helloWorldServicePolish(HelloWorldFactory factory) {
        return factory.createHelloWorldService("pl");
    }

    @Bean
    @Profile("russian")
    public HelloWorldService helloWorldServiceRussian(HelloWorldFactory factory) {
        return factory.createHelloWorldService("ru");
    }
}

DependencyInjectionApplication.java

package com.spring.componentScan;

import com.spring.controllers.GreetingController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.spring")
public class DependencyInjectionApplication {
    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(DependencyInjectionApplication.class, args);
        GreetingController controller = (GreetingController) ctx.getBean("greetingController");
        controller.sayHello();
    }
}

GreetingController.java

package com.spring.controllers;

import com.spring.services.HelloWorldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

@Controller
public class GreetingController {

private HelloWorldService helloWorldService;
private HelloWorldService helloWorldServiceSpanish;

@Autowired
public void setHelloWorldService(HelloWorldService helloWorldService) {
    this.helloWorldService = helloWorldService;
}

@Autowired
@Qualifier("spanish")
public void setHelloWorldServiceFrench(HelloWorldService helloWorldServiceSpanish) {
    this.helloWorldServiceSpanish = helloWorldServiceSpanish;
}

public String sayHello() {
    String greeting = helloWorldService.getGreeting();
    System.out.println(helloWorldServiceSpanish.getGreeting());
    System.out.println(greeting);
    return greeting;
}

}

Application.properties

spring.profiles.active=english
java spring dependency-injection autowired spring-annotations
2个回答
0
投票

如果您考虑此源代码

@Bean(name = "french")
public HelloWorldService helloWorldServiceFrench(HelloWorldFactory factory) {
    return factory.createHelloWorldService("fr");
}

@Bean
public HelloWorldService helloWorldServiceGerman(HelloWorldFactory factory) {
    return factory.createHelloWorldService("de");
}

@Bean
public HelloWorldService helloWorldServicePolish(HelloWorldFactory factory) {
    return factory.createHelloWorldService("pl");
}

@Bean
public HelloWorldService helloWorldServiceRussian(HelloWorldFactory factory) {
    return factory.createHelloWorldService("ru");
}

这里没有@Profile批注,这就是为什么Spring创建多个相同类型的bean的原因,如果您希望它们被不同地识别,请尝试使用@Bean(name="polish")为它们指定完全合格的显式名称(或者Spring总是通过查看[ C0]方法名称),然后使用@Bean

自动接线

0
投票

好的,因此您的示例未使用最新代码进行更新。但是我假设您想创建相同bean类型的多个实例,并将它们用于不同的语言。这很容易实现,因此您不需要@Qualifier("polish")@Profile

[您需要为bean实例分配限定符(或使用spring默认分配的限定符)。然后通过该限定符注入bean。

@Primary

控制器:

@Bean
public HelloWorldService helloWorldServiceFrench(HelloWorldFactory factory) {
    return factory.createHelloWorldService("fr");
}

@Bean
public HelloWorldService helloWorldServiceGerman(HelloWorldFactory factory) {
    return factory.createHelloWorldService("de");
}

@Bean
public HelloWorldService helloWorldServicePolish(HelloWorldFactory factory) {
    return factory.createHelloWorldService("pl");
}

@Bean
public HelloWorldService helloWorldServiceRussian(HelloWorldFactory factory) {
    return factory.createHelloWorldService("ru");
}

更新

通常,当有多个注入候选对象时,想要将一个bean实例作为优先选项时,通常将bean标记为@Controller public class GreetingController { @Qualifier("helloWorldServiceGerman") @Autowired private HelloWorldService helloWorldServiceGerman; @Qualifier("helloWorldServiceFrench") @Autowired private HelloWorldService helloWorldServiceFrench; @Qualifier("helloWorldServicePolish") @Autowired private HelloWorldService helloWorldServicePolish; @Qualifier("helloWorldServiceRussian") @Autowired private HelloWorldService helloWorldServiceRussian; . . . } @Primary

[Official doc with good example只是缩小了bean的搜索范围,但是仍然可以在同一个配置文件中使用多个相同类型的bean-拯救@Profile(如果通过类型自动装配,但通过限定符自动装配仍然可以正常工作)。

开发人员通常这样做是为了避免最初使用的@Primary

© www.soinside.com 2019 - 2024. All rights reserved.