Как ввести бин внутрь для l oop с параметрами - PullRequest
0 голосов
/ 15 января 2020

Могу ли я ввести бобы с параметрами внутри для l oop? Я не хочу инициализировать вручную TheService как в следующем примере:

@Singelton
public class Scheduler {
    @Inject
    private UserQueryService userQueryService;

    @Schedule(hour = "*", minute = "*", second = "*/30", persistent = false)
    public void execute() {
        final List<User> users = userQueryService.findAll();
        for (final User user : users) {
            final TheService service = new TheService(user.getName(), user.getAge());
            service.doSomething();
        }
    }
}

Возможно ли, например, ввести значения времени выполнения из для l oop в метод производителя и внедрить службу с CDI? Я знаю, что строковые и примитивные значения не могут быть введены, но, возможно, вы можете помочь мне и предложить какое-то решение.

@ApplicationScoped
public class TheServiceFactory {
    @Produces
    @RequestScoped
    public TheService createTheService(final String name, final int age) {
        ...
    }
}

Обновление: TheService имеет другие поля с @Inject аннотаций.

Ответы [ 2 ]

1 голос
/ 15 января 2020

Эффективно TheService имеет метод doSomething(), который воздействует на имя пользователя и возраст. TheService имеет и другие зависимости (@Inject ed поля / аргументы конструктора).

Почему бы вам не сделать это явным, сделав TheService @ApplicationScoped и определив аргументы для doSomething(), т.е. :

@ApplicationScoped
public class TheService {
    @Inject DependencyOne dependencyOne;
    @Inject DependencyTwo dependencyTwo;

    public void doSomething(String userName, int age) {
        // use dependencies
    }
}

Если doSomething() действительно нужно сохранять состояние для каждой итерации l oop, например, что вы действительно хотите:

@Schedule(hour = "*", minute = "*", second = "*/30", persistent = false)
public void execute() {
    final List<User> users = userQueryService.findAll();
    for (final User user : users) {
        final TheService service = new TheService(user.getName(), user.getAge());
        service.doSomething();
        // ...
        service.doSomethingElse();
    }
}

Тогда вы можете инкапсулировать состояние в итерация в другом объекте, например (при условии Java> = 8):

// TheServiceWorker.java
public interface TheServiceWorker {
    void doSomething();
    void doSomethingElse();
}

// TheService.java
@ApplicationScoped
public class TheService {
    @Inject DependencyOne dependencyOne;
    @Inject DependencyTwo dependencyTwo;

    public TheServiceWorker makeWorker(String userName, int age) {
        return new TheServiceWorker() {
            public void doSomething() {
                // you can access dependencyOne, dependencyTwo
                // AND userName, age here!
            }

            public void doSomethingElse() {
                // you can access dependencyOne, dependencyTwo
                // AND userName, age here!
            }
        };
    }
}
1 голос
/ 15 января 2020

Я вижу, что вы пытаетесь сделать.

В любой момент вы хотите получить снимок всех User с в системе. Затем для каждого из них вы хотите, чтобы существовал RequestScoped TheService, который затем будет использоваться для каких-либо действий.

Как написано, на самом деле это невозможно с CDI.

Я предполагаю, что вы хотите создать экземпляр TheService и использовать механизм зависимостей CDI, поскольку TheService имеет некоторые @Inject -аннотированные поля? Я просто догадываюсь.

Если это так, вы можете подделать это примерно так:

final Unmanaged<TheService> unmanagedService = new Unmanaged<TheService>(TheService.class);
final UnmanagedInstance<TheService> serviceInstance = unmanagedService.newInstance();
final TheService service = serviceInstance.produce().inject().postConstruct().get();
// Any @Inject-annotated fields in service will now be "filled" if possible; that's
// what the inject() call above does; any @PostConstruct methods it has will have been
// invoked, etc.
// You'll have to manually set its user and age properties:
service.setUser(user.getName());
service.setAge(user.getAge());
service.doSomething();
// The TheService instance is NOT in request scope; *you* are fully in control
// of its lifecycle, so don't forget to dispose it when you're done.  You may
// need to put this in a finally block to ensure it happens:
serviceInstance.preDestroy().dispose();

Компоненты CDI имеют «stati c» дизайн. То, что вы хотите сделать, это dynamici c, то есть он изменяется во время выполнения (возможно, служба запросов возвращает совершенно разные User экземпляры при каждом вызове). Поэтому внедрение полностью управляемого TheService на самом деле не то, что вы хотите сделать, поскольку вы не можете предсказать, сколько их будет или как они будут построены.

Конструкция Unmanaged в CDI предназначен для тех случаев, когда вы хотите управлять продолжительностью жизни чего-либо, что в противном случае было бы бином CDI самостоятельно.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...