分层架构中的CDI.如何使用CDI注释注入服务对象?

riv*_*ket 5 dependency-injection layer cdi jsf-2

我正在开发一些应用程序,它由三层组成:

  1. 数据库访问层(JPA + Hibernate作为提供者)
  2. 业务逻辑层
  3. 表示层(JSF 2.0)

在开始之前,我已经阅读了David Geary和Cay S. Horstmann撰写的Core JavaServer Faces(第3版)一书中的一些章节.在本书中,作者强烈建议使用@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
}
Run Code Online (Sandbox Code Playgroud)

AccountService.java:

public interface AccountService {
    public Boolean verifyCredentials(String login, String password);
}
Run Code Online (Sandbox Code Playgroud)

AccountServiceImpl.java:

public class AccountServiceImpl implements AccountService {
    @Inject
    AccountDAO dao;

    @Override
    public Boolean verifyCredentials(String login, String password) {
        // some logic
    }
}
Run Code Online (Sandbox Code Playgroud)

AccountDAO.java :

public interface AccountDAO {
    public Account getAccount(String login);
}
Run Code Online (Sandbox Code Playgroud)

AccountDAOImpl.java :

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
    }
}
Run Code Online (Sandbox Code Playgroud)

最后一个类在带有@Entity注释的一些Java类上运行,没关系.

我觉得我的解决方案有问题.

基本错误是事实,即使我提供一些数据与创建的窗体<h:form>,<h:inputText>标签,调试时verify()的方法我可以看到,loginpasswordnull,所以什么是错在这里,但我不知道是什么.

如果我理解得@Inject很好,我也会担心.我可以像上面提到的那样使用接口来耦合图层吗?


好.我找到了为什么我在登录和密码字段上得到空值的原因,但我还不知道解决方案.之所以发生这种情况,是因为在以某种神奇的方式执行期间,创建了多个(至少两个)CredentialsBean实例.签入Eclipse调试器.首先正确设置其字段,但第二个字段设置不正确,并将第二个字段的值发送到服务层.我想知道这不是范围问题.我不应该把@SessionScoped放在CredentialsBean中吗?

Lig*_*ard 1

你的理解@Inject是正确的,这正是它的用途。您的注入点很可能为空,因为您没有 bean 存档(您需要 WEB-INF 或 META-INF 中名为 beans.xml 的文件,如果它是 jar,则它可以为空)。这是注入点为 null 的常见原因。