zolt85
@zolt85
Программист

Как заменить одну реализацию другой в списке однотипных бинов?

Всем привет.

Наткнулся я на такой кейс и задумался.
Смотрите. Есть у меня интерфейс SimpleBean, например.
package com.example.beans;

public interface SimpleBean {

    String getName();
}

Есть три реализации этого интерфейса: FirstBean, SecondBean и ThirdBean, соответственно.
package com.example.beans;

import org.springframework.stereotype.*;

@Component
public class FirstBean implements SimpleBean {
    @Override
    public String getName() {
        return "First Bean";
    }
}

package com.example.beans;

import org.springframework.stereotype.*;

@Component
public class SecondBean implements SimpleBean {
    @Override
    public String getName() {
        return "Second Bean";
    }
}

package com.example.beans;

import org.springframework.stereotype.*;

@Component
@Primary
public class ThirdBean extends FirstBean {

    @Override
    public String getName() {
        return "I'm inherited " + super.getName() + " and my name is Third Bean";
    }
}


Товарищ ThirdBean отличается от остальных тем, что он не реализует на прямую SimpleBean, а наследует FirstBean.

Есть некий контроллер, назовем его DemoController:
package com.example.controllers;

import com.example.beans.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@Controller
public class DemoController {

    private List<SimpleBean> myBeans;

    /** */
    @Autowired
    public DemoController(List<SimpleBean> myBeans) {
        this.myBeans = myBeans;
    }

    /** */
    @RequestMapping("/")
    @ResponseBody
    public String hello() {
        StringBuilder beansNames = new StringBuilder();
        myBeans.forEach(bean -> beansNames.append(bean.getName()).append("\n"));
        return beansNames.toString();
    }
}


Как Вы можете видеть, в контроллер, через конструктор, внедряется список из SimpleBean.
Собственно кейс в том, чтобы в этом списке не было FirstBean, т.к. его наследует ThirdBean.

Сейчас внедряется список из всех трёх бинов. Аннотация @Primary на ThirdBean не решает проблему.
Может кто-то решал подобную задачу, подскажите в какую сторону копать?
  • Вопрос задан
  • 182 просмотра
Решения вопроса 1
jaxtr
@jaxtr
JavaEE/Spring-разработчик
Для этого существует аннотация @Conditional. Если используется Spring Boot, то у него есть @ConditionalOnMissingClass, которая позволяет указать, что отмеченный компонент нужно создавать, если не найден указанный класс:
@ConditionalOnMissingClass(ThirdBean.class)
@Component
public class FirstBean implements SimpleBean {
    @Override
    public String getName() {
        return "First Bean";
    }
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@LooksWorking
А профили не подойдут?
Аннотируете ваших имплементаторов
@Profile("SimpleBean-third")
И при запуске указываете активные профили, проинжектится соответствующая имплементация SimpleBean.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы