【问题标题】:Generics and Dependency Injection in JavaJava中的泛型和依赖注入
【发布时间】:2017-07-26 14:47:33
【问题描述】:

我正在开发一个将 JAX-RS 用于 WebLayer 的 Java EE 应用程序。

我试图解决这个问题。因此,您将看到的代码只是一个剪切。目前一切正常。如您所见,我有一个UserEndpoint,客户端可以在其中创建新用户。一切完成后,VerificationService 会发送一封验证邮件。

用户端点

@Path("/users")
@Stateless
public class UserEndpoint {

    @Inject
    @AuthenticatedUser
    private User authenticatedUser;

    @EJB
    private UserDAO userDAO;

    @EJB
    private TokenDAO tokenDAO;

    @Inject
    private PasswordValidator passwordValidator;

    @Inject
    private UserValidator validator;

    @Inject
    private VerificationService verificationService;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public User createUser(User user) {

        // Validation and Creation

        // Verification
        this.verificationService.sendVerificationMail(user);

        return user;
    }
}

验证服务

@Singleton
public class VerificationService {

    @Inject
    private MailService mailSender;

    @Inject
    private TemplateService templateService;

    public void sendVerificationMail(User user) {
        this.templateService.setUserTemplate(TemplateCategory.VerificationTemplate, user);
        mailSender.sendMail(new Message(
            MessageDAO.systemEmailAddresses.get(0),
            user.getEmail(),
            templateService.getSubject(),
            templateService.getContent()));
    }
}

因为我想要一个可扩展的项目,所以我决定封装端点的一部分,这样我就可以在其他项目中使用它。由于每个用户都必须以一种或另一种方式进行验证,我认为封装验证过程是一个好主意。问题是我不知道如何实现这一点。我的第一种方法如下:

CoreUserEndpoint

@Path("/users")
@Stateless
public abstract class CoreUserEndpoint<D extends BaseUserDAO<T>, T extends BaseUser, V extends CoreUserValidator<D, T>> extends EntityEndpoint<D, T, V> {

    @EJB
    private TokenDAO tokenDAO;

    @Inject
    private PasswordValidator passwordValidator;

    @Inject
    private VerificationService<T> verificationService;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public User createUser(User user) {

        // Validation and Creation

        // Verification
        this.verificationService.sendVerificationMail(user);

        return user;
    }
}

实体端点

@Stateless
public class EntityEndpoint<D extends CoreDAO<T>, T extends CoreEntity, V extends CoreValidator> {

    protected D entityDAO;

    @Inject
    @AuthenticatedUser
    protected T authenticatedUser;

    protected V entityValidator;

}

验证服务

@Singleton
public class VerificationService<T extends BaseUser> {

    @Inject
    private MailService mailSender;

    @Inject
    private TemplateService<T> templateService;

    public void sendVerificationMail(User user) {
        this.templateService.setUserTemplate(TemplateCategory.VerificationTemplate, user);
        mailSender.sendMail(new Message(
            MessageDAO.systemEmailAddresses.get(0),
            user.getEmail(),
            templateService.getSubject(),
            templateService.getContent()));
    }
}

当我尝试这个时,我得到了著名的WELD-001408: Unsatisfied dependencies 错误。我想我确实理解为什么会这样。当我读到here 时,我不能使用泛型,既不能用于@Inject,也不能用于@EJB。但是,如果我不能使用泛型,我该如何封装我的项目的核心?他们是否有任何解决方法或不同的方法?我确信互联网上的任何地方都已经有解决方案。但是经过 3 天的搜索没有取得任何进展,我真的很沮丧,并认为最好问问你们。因此,如果您能指出正确的方向,我将不胜感激。

【问题讨论】:

    标签: java generics dependency-injection


    【解决方案1】:

    我只是想理解其中的逻辑。由于我的问题太长了,我决定在 aswer 部分发帖。

    免责声明:它不会直接回答您的问题

    那么,让我们开始吧:

    泛型类的定义格式如下:

    class name&lt;T1, T2, ..., Tn&gt; { /* ... */ }类型参数部分, 由尖括号 () 分隔,跟在类名之后。它指定 类型参数(也称为类型变量)T1, T2, ..., and Tn.

    1. 所以通过这样做:

    public abstract class CoreUserEndpoint<D extends BaseUserDAO<T>, T extends BaseUser, V extends CoreUserValidator<D, T>>
    

    类型变量D extends BaseUserDAO&lt;T&gt;, T extends BaseUser, V extends CoreUserValidator&lt;D, T&gt;,指示Java编译器为了使用CoreUserEndpoint需要指定类型。

    2. 下一步当你这样做时:

    public abstract class CoreUserEndpoint<...> extends EntityEndpoint<D, T, V> 
    

    您使用先前定义的类型参数将在EntityEndpoint 中使用。现在,编译器将查找名为 D、T 和 V 的类(或接口,...)。

    这是我不确定的部分。如果编译器从您对CoreUserEndpoint 的声明中找到它们,那么您正试图通过执行以下操作强制该类从多个类扩展,这是不允许的:

    public class EntityEndpoint<D extends CoreDAO<T>, T extends CoreEntity, V extends CoreValidator>
    

    附注如果我在这里写的内容有任何意义,我将非常感谢来自经验 Java 开发人员的任何反馈。

    【讨论】:

    • 我认为public class EntityEndpoint&lt;D extends CoreDAO&lt;T&gt;, T extends CoreEntity, V extends CoreValidator&gt; 不应该导致任何错误。事实上,如果我在VerificationService 中使用TemplateService&lt;User&gt; 而不是TemplateService&lt;T&gt; 并保留代码原样,我不会得到任何异常。但我无法从技术角度解释这种说法。
    • 如果您的项目有一个公共仓库,我不介意克隆它并想知道它:) 我可能会更好地了解您的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 2020-03-25
    相关资源
    最近更新 更多