简体   繁体   中英

Autowired not wiring bean by Type

I have an interface( X ) with a method which prints out a statement and the interface has 2 implementations of it X1 and X2 and there is this class Y which has 2 objects of X autowired by type for X1 and X2 with the interface. ie, like private X x; and private X x2; and when I call x.statement() it prints the default profile statement but when x2.statement() is called it still prints the x.statement() print statement instead of x2.statement() .

BTW I am using Spring boot.

public interface HelloWorldService {
    public String getGreeting();
}

@Component
@Profile({ "default", "english" })
public class HelloWorldServiceEnglishImpl implements HelloWorldService {
    @Override
    public String getGreeting() {
        return "Hello World";
    }
}

@Component
@Profile("spanish")
public class HelloWorldServiceSpanishImpl implements HelloWorldService {
    @Override
    public String getGreeting() {
        return "Hola Mundo";
    }
}

-

@Controller
public class GreetingController {

    @Autowired
    private HelloWorldService helloWorldService;

    @Autowired
    private HelloWorldService helloWorldServiceSpanish;

    public void setHelloWorldServiceSpanish(HelloWorldServiceSpanishImpl helloWorldServiceSpanish) {
        this.helloWorldServiceSpanish = helloWorldServiceSpanish;
    }

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

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

Firstly, what makes you think one of the Injected beans will be the 'English' bean and one will be the 'Spanish' bean. You inject two instances of the bean defined by the active profile: the 'English' bean. There is no Bean HelloWorldServiceKannadaImpl active for this profile. So both instances are instances of HelloWorldServiceEnglishImpl.

    //this code is not called. The instance variable is auto-wired by field
    //and the auto-wired bean is the only one available: the English one.
    public void setHelloWorldServiceSpanish(HelloWorldServiceSpanishImpl helloWorldServiceSpanish) {
        this.helloWorldServiceSpanish = helloWorldServiceSpanish;
    }

How it should be:

@Controller
public class GreetingController {

    //will be English or Spanish depending on Active profile.
    @Autowired
    private HelloWorldService helloWorldService;

    public void sayHello() {
        String greeting = helloWorldService.getGreeting();
        System.out.println(greeting);

    }
}

In your original code either remove the @Profile from the two beans, or change to spring.profiles.active=english,spanish and it might work as you expect. Although having both kinds of defeats the whole purpose which is to have dynamically injected bean based on the runtime environment.

At a time, only one Profile will be ACTIVE depending upon the set value, so you either can be able to print English or Spanish, but NOT both as per your config.

You can look at here for more details.

If you want to be able to inject the two beans of the same type at the same time you shouldn't bind them to profiles: you can assign them different names.

@Component("english")
public class HelloWorldServiceEnglishImpl implements HelloWorldService {
    @Override
    public String getGreeting() {
        return "Hello World";
    }
}

@Component("spanish")
public class HelloWorldServiceSpanishImpl implements HelloWorldService {
    @Override
    public String getGreeting() {
        return "Hola Mundo";
    }
}

then you can inject them with the @Named (java api) or @Qualifier (spring api) (if I remember it correctly) annotation

@Named("english") // @Qualifier("english")
@Autowired
private HelloWorldService helloWorldService;

@Named("spanish") // @Qualifier("spanish")
@Autowired
private HelloWorldService helloWorldServiceSpanish;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM