对象的@Inject注释以及此对象的两种不同行为 [英] @Inject annotation for object and two different behaviors of this object
问题描述
我使用JSF 2.2和CDI.我创建了以下示例,以向您展示我的问题的核心.您可以在下面看到:
I use a JSF 2.2 and CDI. I created below example to show you a heart of my problem. You can see below:
- 两个xhtml页面,
- 会话范围的CDI bean(
LoginController
),它是xhtml page1的控制器, - 视图作用域CDI bean(
DataController
),它是xhtml page2的控制器, - 请求范围的CDI bean(
DataServiceImpl
),它是DataController
bean的服务.
- the two xhtml pages,
- the session scoped CDI bean (
LoginController
) which is the controller for the xhtml page1, - the view scoped CDI bean (
DataController
) which is controller for the xhtml page2, - the request scoped CDI bean (
DataServiceImpl
) which is the service for theDataController
bean.
这是一个用例和数据流:
This is a use case and flow of the data:
xhtml page2-> DataController
控制器->在send()
方法(位于DataController
类中)中调用dataService.addData()
->执行addData()
方法(位于DataServiceImpl
中)课
xhtml page2 -> the DataController
controller -> call dataService.addData()
in send()
method (which is located in the DataController
class) -> execute addData()
method (which is located in the DataServiceImpl
class)
我的问题的核心:
- 如果将
LoginController
注入到DataServiceImpl
类中,则loginController
对象不起作用(即,它返回null
)[下面的代码中的选项1]. - 如果将
LoginController
注入到DataController
类中,则loginController
对象可以正常工作(即,它返回我想要的内容)[下面的代码中的选项2].
- If I inject the
LoginController
to theDataServiceImpl
class, theloginController
object doesn't work (i.e. it returnsnull
) [Option 1 in the code below]. - If I inject the
LoginController
to theDataController
class, theloginController
object works fine (i.e. it returns what I want) [Option 2 in the code below].
我的问题是:为什么这个注入的对象根据注入的位置以两种不同的方式表现?
My question is: Why this injected object behaves in two different ways depending on place of injection?
这是我的xhtml page1的一部分:
This is the part of my xhtml page1:
<h:form>
<p:growl id="growl" showDetail="false" />
<h:inputText id="username" value="#{userLogin.username}" label="Username" required="true" requiredMessage="Username: This field is required." title="Enter your username." pt:placeholder="Username" />
<h:inputSecret id="password" value="#{userLogin.password}" label="Password" required="true" requiredMessage="Password: This field is required." title="Enter your password." pt:placeholder="Password" />
<p:commandButton value="Login" action="#{loginController.login}" update="growl" />
</h:form>
这是我的xhtml page2的一部分:
This is the part of my xhtml page2:
<h:form>
<p:growl id="growl" showDetail="false" />
<p:panelGrid id="panel" columns="2" styleClass="ui-noborder" columnClasses="rightalign,leftalign">
<p:outputLabel for="data" value="Data:" />
<p:inputText id="data" value="#{data.text}" required="true" requiredMessage="Data: This field is required." />
<p:commandButton id="buttonSend" value="Send" action="#{dataController.send()}" update="messages" />
</p:panelGrid>
</h:form>
这是会话范围的CDI bean:
This is the session scoped CDI bean:
@Named
@SessionScoped
public class LoginController implements Serializable {
private static final long serialVersionUID = -6322113716363932422L;
public String login(){
if(userService.login(userLogin)){
currentUser=userService.getCurrnetUser(userLogin.getUsername());
return "home?faces-redirect=true";
}
else{
facesContext.addMessage(null, new FacesMessage("Data entered are incorrect"));
return null;
}
}
public String logout(){
currentUser=null;
return "login?faces-redirect=true";
}
public boolean isLoggedIn() {
return currentUser!=null;
}
@Produces
@LoggedIn
public UserAccount getCurrentUser(){
return currentUser;
}
@Inject
private FacesContext facesContext;
@Inject
private UserServiceImpl userService;
@Named
@Produces
@RequestScoped
private UserAccount userLogin=new UserAccount();
private UserAccount currentUser;
}
这是视图范围内的CDI bean:
This is the view scoped CDI bean:
@Named
@ViewScoped
public class DataController implements Serializable {
private static final long serialVersionUID = 1383572529241805730L;
public void send(){
/* OPTION 2
* If I inject the LoginController here
* instead of in DataServiceImpl bean, the loginController object
* works fine (i.e. it isn't null and returns the name of the user).
*/
String name=loginController.getCurrentUser().getName();
dataService=new DataServiceImpl();
dataService.addData(data.getText);
}
@Named
@Produces
@RequestScoped
private Data data=new Data();
@Inject
private DataService dataService;
@Inject
private LoginController loginController;
}
这是请求范围内的CDI bean:
This is the request scoped CDI bean:
@Named
@RequestScoped
public class DataServiceImpl implements DataService {
@Override
public void addData(String data) {
/* OPTION 1
* If I inject the LoginController here
* instead of DataController bean, the loginController object
* doesn't work (i.e. returns null. I get the NullPointerException exception
* in line below due to the loginController object which is null)
*/
String name=loginController.getCurrentUser().getName();
//Proccess some data
}
@Inject
private LoginController loginController;
}
推荐答案
我不太了解您的设计,这可能是问题的一部分.
I don't really understand your design, and this may be part of the problem.
您不应将一个控制器注入另一个控制器,也不应将一个控制器注入服务.
You shouldn't inject a controller into another controller, or inject a controller into a service.
看到您的LoginController
生成了@LoggedIn UserAccount
,为什么不简单地注入它,而不是注入loginController
并调用loginController.getCurrentUser().getName()
?
Seeing that your LoginController
produces a @LoggedIn UserAccount
, why not simply inject that, instead of injecting the loginController
and calling loginController.getCurrentUser().getName()
?
这篇关于对象的@Inject注释以及此对象的两种不同行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!