Понимание экземпляра cdi <> и .get () против @Inject - PullRequest
8 голосов
/ 27 марта 2012

Я немного запутался по поводу того, что использовать в следующей ситуации:

Предположим, сервлет создает Приложение, которое обрабатывает сеанс http пользователя, и это приложение:

public class Application extends AbstractHTTPApplication {

@Inject
private Instance<MainView> mainView;

public void setupApplication() {
   this.setView( mainView.get() );
}

Позже у меня есть @SessionScoped бин SSB, который я хочу внедрить в бин каждого пользователя:

@SessionScoped
public class SSB {}

Теперь, когда я попробовал обычный @Inject SSB ssb; в качестве поля в MainViewЯ не получаю новый SSB для каждого пользователя:

public class MainView {

@Inject
private SSB usersSSB;

   public someMethod() {
       usersSSB.doSomething();
       System.identityHashCode( usersSSB );
   }
}

Тестируя с двумя пользователями, я получаю одинаковый экземпляр usersSSB в обоих сеансах пользователя.Я не думал, что это было возможно ... Я думал, что, поскольку SSB является SessionScoped, каждому сеансу пользователя будет даваться новый, и независимо от того, где он находится @Inject, он будет ссылаться на , что пользователь SSB.

Вместо этого я попытался:

public class MainView {

@Inject
private Instance<SSB> usersSSB;

   public someMethod() {
       usersSSB.get().doSomething();
       System.identityHashCode( usersSSB.get() );
   }
}

Теперь он сообщает разные usersSSB для каждого пользователя, наконец.

Что здесь происходит?Когда позже я вызову usersSSB.get() в сеансе каждого пользователя, будет ли usersSSB.get() возвращать одного и того же компонента для одного и того же пользователя каждый раз?

Яработает на Glassfish 3.1.2.

Некоторая дополнительная информация

Класс приложения внедряется в сервлет при новом запросе HttpServlet:

public abstract class AbstractCdiApplicationServlet extends
    AbstractApplicationServlet {
@Inject
protected Instance<ApplicationWrapper> wrapper;

@Override
protected Application getNewApplication(HttpServletRequest request)
        throws ServletException {
    return wrapper.get().getApplication();
}
...etc etc

И ApplicationWrapper - это SessionScoped bean-компонент:

@SuppressWarnings("serial")
@SessionScoped
public class ApplicationWrapper implements Serializable {
@Inject
private AbstractCdiApplication application;

public AbstractCdiApplication getApplication() {
    return application;
}
 }

Не означает ли это, что вызов @Inject SSB usersSSB в любом месте MainView (или любого объекта в сеансе этого пользователя)должен дать мне этот пользовательский сессионный компонент и всегда тот же самый сессионный компонент для сеанса каждого пользователя?Значение - разные пользователи SSB для разных пользователей, потому что у каждого пользователя свой сеанс.

В конце концов, сам Application является компонентом SessionScoped, внедренным и присоединенным к сеансу HTTP пользователя с помощью getNewApplication метод сервлета?Я имею в виду, что именно объект Application внедряет и присоединяет класс MainView, в конце концов, верно?Так что это означает, что MainView - это сессионный компонент, не так ли?

Я просто пытаюсь понять, как все это работает, я полагаю.Спасибо за помощь!

1 Ответ

7 голосов
/ 28 марта 2012

Это происходит из-за того, что @Inject Instance <> динамически получается, в отличие от @ Inject

Если вы вводите '@Inject' в bean-компонент ApplicationScoped, то инъекция получается только один раз, поэтому в bean-компоненте ApplicationScoped эта ссылка будет одинаковой для всех пользователей

Если вы вызываете .get () в «@Inject Instance <>», то ссылка на SSB получается динамически каждый раз, когда вы вызываете .get ()

Подробнее о инъекции вы можете прочитать здесь: http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/injection.html

...