Dependency injection 分层体系结构中的CDI。如何使用CDI注释注入服务对象?
我正在开发一些应用程序,它由三层组成:Dependency injection 分层体系结构中的CDI。如何使用CDI注释注入服务对象?,dependency-injection,jsf-2,layer,cdi,Dependency Injection,Jsf 2,Layer,Cdi,我正在开发一些应用程序,它由三层组成: 数据库访问层(JPA+Hibernate作为提供程序) 业务逻辑层 表示层(JSF2.0) 在开始之前,我已经阅读了DavidGeary和CayS.Horstmann的《核心JavaServerFaces》(第三版)一书中的一些章节。在本书中,作者强烈建议使用@Named注释而不是@ManagedBean。好的,我想我可以试试 然后,我通过实现一些基本功能(用户登录)继续构建我的应用程序 我还阅读了一些新的注释,即@Inject。我认为仅仅基于接口将一个层
@Named
注释而不是@ManagedBean
。好的,我想我可以试试
然后,我通过实现一些基本功能(用户登录)继续构建我的应用程序
我还阅读了一些新的注释,即@Inject
。我认为仅仅基于接口将一个层注入另一个层是非常舒服的。但是我恐怕我误解了什么,所以我带着我的问题来找你
让我介绍我的代码的一些部分:
CredentialsBean.java:
@Named("userCredentials")
public class CredentialsBean {
@Inject
AccountService accountService;
private String login;
private String password;
public String verify()
{
if (accountService.verifyCredentials(login, password))
return "success";
else
return "failure";
}
// getters and setters
}
public interface AccountService {
public Boolean verifyCredentials(String login, String password);
}
public interface AccountDAO {
public Account getAccount(String login);
}
public class AccountDAOImpl implements AccountDAO {
@PersistenceContext(unitName = "MyApp")
protected EntityManager em;
public EntityManager getEntityManager() {
return em;
}
@Override
public Account getAccount(String login) {
// some data processing
}
}
AccountService.java:
@Named("userCredentials")
public class CredentialsBean {
@Inject
AccountService accountService;
private String login;
private String password;
public String verify()
{
if (accountService.verifyCredentials(login, password))
return "success";
else
return "failure";
}
// getters and setters
}
public interface AccountService {
public Boolean verifyCredentials(String login, String password);
}
public interface AccountDAO {
public Account getAccount(String login);
}
public class AccountDAOImpl implements AccountDAO {
@PersistenceContext(unitName = "MyApp")
protected EntityManager em;
public EntityManager getEntityManager() {
return em;
}
@Override
public Account getAccount(String login) {
// some data processing
}
}
AccountServiceImpl.java:
AccountDAO.java:
@Named("userCredentials")
public class CredentialsBean {
@Inject
AccountService accountService;
private String login;
private String password;
public String verify()
{
if (accountService.verifyCredentials(login, password))
return "success";
else
return "failure";
}
// getters and setters
}
public interface AccountService {
public Boolean verifyCredentials(String login, String password);
}
public interface AccountDAO {
public Account getAccount(String login);
}
public class AccountDAOImpl implements AccountDAO {
@PersistenceContext(unitName = "MyApp")
protected EntityManager em;
public EntityManager getEntityManager() {
return em;
}
@Override
public Account getAccount(String login) {
// some data processing
}
}
AccountDAOImpl.java:
@Named("userCredentials")
public class CredentialsBean {
@Inject
AccountService accountService;
private String login;
private String password;
public String verify()
{
if (accountService.verifyCredentials(login, password))
return "success";
else
return "failure";
}
// getters and setters
}
public interface AccountService {
public Boolean verifyCredentials(String login, String password);
}
public interface AccountDAO {
public Account getAccount(String login);
}
public class AccountDAOImpl implements AccountDAO {
@PersistenceContext(unitName = "MyApp")
protected EntityManager em;
public EntityManager getEntityManager() {
return em;
}
@Override
public Account getAccount(String login) {
// some data processing
}
}
最后一个类在一些带有@Entity
注释的Java类上操作,无需担心
我觉得我的解决方案有问题
基本的错误是,即使我向使用
,
标记创建的表单提供了一些数据,在调试verify()
方法时,我可以看到,login
和password
都是null
,所以这里有些错误,但我不知道是什么
我还担心我是否理解@Inject
很好。我可以像上面提供的那样使用它来使用接口耦合层吗
嗯。我找到了登录和密码字段为空的原因,但我还不知道解决方案。 之所以发生这种情况,是因为在以某种神奇的方式执行期间,创建了多个(至少两个)CredentialsBean实例。签入Eclipse调试器。第一个字段设置正确,但第二个字段设置不正确,第二个字段的值被发送到服务层。
我想知道这是否不是一个范围问题。我不应该把@SessionScoped放在CredentialsBean中吗?你对
@Inject
的理解是正确的,这正是它的目的。您的注入点很可能是空的,因为您没有bean存档(您需要在WEB-INF或META-INF中有一个名为beans.xml的文件,如果它是jar,它可以是空的)。这是在注入点中使用null的常见原因。我认为问题在于CredintialsBean类。您没有为bean指定作用域,因此它使用默认作用域(有关更多信息,请参阅)
如果向类中添加类似@RequestScoped的内容,它应该可以工作。确保您使用的是javax.enterprise.context.RequestScoped,而不是javax.faces版本。您的实现类没有
@Named
注释。这是故意的还是过于简化了代码片段?他们必须这样做吗?我认为只有用于在JSF页面和应用程序逻辑之间传输信息的bean才需要它。我错了吗?@Stateless
如果它应该是一个EJB,那么它也可以。容器还应该如何知道您有哪些实现以及需要注入哪些实现?我不理解您的回答。我想我不需要EJB。我创建层是为了允许不同的对象使用服务层,即JSFbean执行一些任务,HttpServlet执行另一些任务。我不认为我需要EJB组件,只是AccountDAOImpl
是一个典型的@无状态
EJB实现。如果您想将其命名为,
,可以,但您必须自己管理事务。但这并不是我评论的真正目的。关键是,如果您不注释实现,容器如何知道您有哪些实现以及需要注入哪些实现?不幸的是,这不是正确的解决方案。从eclipse项目配置开始,WebContent/WEB-INF目录中就有beans.xml。我的登录名和密码仍然为空。有什么想法吗?我不明白你怎么会得到空值而不是异常。