Как вы создаете прототип @Bean с аргументами времени выполнения?С getBean (имя строки, объект ... аргументы)? - PullRequest
0 голосов
/ 26 мая 2018

Как вы создаете прототип @Bean с аргументами времени выполнения?С getBean(String name, Object... args)?Мой вопрос является следствием этого вопроса .

Почему этот подход не используется или не упоминается в документации Spring IoC ?

Это нормальный подход ?Есть ли более правильный подход для создания прототипа @Bean с аргументами времени выполнения?

Если это не нормальный подход, можете ли вы объяснить, почему?Обратите внимание, что мне нужно установить мои аргументы через конструктор, не через сеттеры.

@Autowired
private ApplicationContext appCtx;

public void onRequest(Request request) {
    //request is already validated
    String name = request.getParameter("name");
    Thing thing = appCtx.getBean(Thing.class, name);

    //System.out.println(thing.getName()); //prints name
}

-

public class Thing {

    private final String name;

    @Autowired
    private SomeComponent someComponent;

    @Autowired
    private AnotherComponent anotherComponent;

    public Thing(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }
}

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Это возможно с помощью фабрики бинов:

@Configuration
public class ThingProvider {

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Thing create(String name) {
        return new Thing(name);
    }

}

Использование:

@Component
public class SomeBean {

    @Autowired
    private ThingProvider thingProvider;

    public void onRequest(Request request) {

        String name = request.getParameter("name");
        Thing thing = myProvider.create(name);
    }

}

То, что часто выдвигается в качестве аргумента против appCtx.getBean(Thing.class, name), это то, что оно требуетдля жесткой проволоки Spring конкретных классов.Кроме того, в случае изменения конструктора Thing проверка времени компиляции не производится.

0 голосов
/ 26 мая 2018

С точки зрения инжектора конструктора, нет.Тем не менее, вы можете задать Thing метод init и использовать ObjectFactory:

@Autowired
private ObjectFactory<Thing> thingFactory;

public void onRequest(Request request) {
    //request is already validated
    Thing thing = thingFactory.getObject();
    thing.init("name");

    //System.out.println(thing.getName()); //prints name
}

с вещью:

@Component
@Scope("prototype")
public class Thing {

    private String name;

    @Autowired
    private SomeComponent someComponent;

    @Autowired
    private AnotherComponent anotherComponent;

    public init(String name) {
        this.name = name;
    }

}

К сожалению, name может 't final, поскольку это не через конструктор.Хотелось бы узнать, есть ли лучшие способы сделать это с constructor injection.

...