有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java理解概要文件中的主要注释

我试图从这个video中理解@Primary在@Profile中的行为

使用profile进行依赖注入。 文件应用程序中的活动配置文件。属性为english,运行它会产生错误

expected single matching bean but found 2: helloWorldServiceEnglish,helloWorldServiceSpanish

在helloConfig中添加@Primary注释。java解决了这个错误:

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

当我使用Profile自动连接时,只有一个名为english的配置文件,那么为什么它要搜索其他没有@Profile注释的bean呢?添加@Primary如何改变这种行为

Spring是否首先在内部按类型扫描Autowire,并完全忽略@Profile,因为它会抛出错误expected single matching bean but found 2

你好。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");
    }
}

依赖注入应用程序。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();
    }
}

欢迎控制器。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;
    }
}

应用程序。属性 春天个人资料。主动=英语

Complete Source code:


共 (2) 个答案

  1. # 1 楼答案

    好的,你的例子没有更新最新的代码。但我假设您想要创建同一bean类型的多个实例,并将它们用于不同的语言。这很容易实现,你不需要@Profile@Primary来实现

    您需要的只是为bean实例分配限定符(或者使用spring默认分配的限定符)。以及这个限定符的注入bean

    @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");
    }
    

    控制器:

    @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;
        . . .
    }
    

    更新

    当有多个注入候选时,如果希望将一个bean实例作为优先级选项,通常会将bean标记为@PrimaryOfficial doc with good example

    @Profile只是缩小了bean搜索的范围,但如果在同一个概要文件中有多个相同类型的bean,仍然需要进行解救(如果按类型自动连接,则按限定符自动连接仍然可以正常工作)

    开发人员通常这样做是为了避免最初的NoUniqueBeanDefinitionException

  2. # 2 楼答案

    如果你考虑这个源代码

    @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通过查看@Bean方法名来指定它们),然后使用@Qualifier("polish")自动连线