简体   繁体   English

Java中的泛型和依赖注入

[英]Generics and Dependency Injection in Java

I am developing a Java EE application that uses JAX-RS for the WebLayer. 我正在开发将JAX-RS用于WebLayer的Java EE应用程序。

I tried to break down the problem. 我试图解决这个问题。 So the code you'll see is just a cutout. 因此,您将看到的代码只是一个切口。 For now everything works fine. 现在一切正常。 As you can see I have an UserEndpoint where a client can create a new user. 如您所见,我有一个UserEndpoint ,客户端可以在其中创建新用户。 After everything is done a verification mail is sent by the VerificationService . 完成所有操作后, VerificationService将发送一封验证邮件。

UserEndpoint UserEndpoint

@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;
    }
}

VerificationService VerificationService

@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()));
    }
}

Because I want to have a scalable project I decided to encapsulate parts of the endpoint, so I can make use of it in other projects. 因为我想要一个可伸缩的项目,所以我决定封装端点的某些部分,因此可以在其他项目中使用它。 Since every user has to be verified in one way or another I thought that the encapsulation of the verification process would be a good idea. 由于必须以一种或另一种方式验证每个用户,因此我认为封装验证过程将是一个好主意。 The problem is that I have no clue how to realize that. 问题是我不知道如何实现这一点。 My first approach was as followed: 我的第一种方法如下:

CoreUserEndpoint 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;
    }
}

EntityEndpoint EntityEndpoint

@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;

}

VerificationService VerificationService

@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()));
    }
}

When I tried this I get the famous WELD-001408: Unsatisfied dependencies error. 当我尝试这样做时,我得到了著名的WELD-001408: Unsatisfied dependencies错误。 And I think I do understand why this is happening. 而且我想我确实理解为什么会这样。 As I read here I cannot make use of generics, neither for @Inject nor for @EJB . 正如我在这里阅读的那样我无法使用@Inject@EJB的泛型。 But if I am not able to use generics how can I encapsulate the core of my project? 但是,如果我不能使用泛型,该如何封装项目的核心? Is their any work around or a different approach? 他们有没有解决的方法或不同的方法? I am sure there already is a solution for that anywhere in the internet. 我相信互联网上任何地方都已经有解决方案。 But after 3 days of searching without making any progress I get really frustrated and thought It would be best to ask you guys. 但是经过三天的搜索却没有取得任何进展,我感到非常沮丧,并认为最好问问你们。 So I would really appreciate if you could point me in the right direction. 因此,如果您能指出正确的方向,我将不胜感激。

I'm just trying to understand the logic. 我只是想了解逻辑。 Since my comments with questions are too long, I decided to post here in aswer section. 由于我对问题的评论过长,因此我决定将其发布在aswer部分。

Disclaimer: It doesn't answer you question directly 免责声明: 它不会直接回答您的问题

So, let's start: 因此,让我们开始:

A generic class is defined with the following format: 通用类以以下格式定义:

class name<T1, T2, ..., Tn> { /* ... */ } The type parameter section, delimited by angle brackets (<>), follows the class name. class name<T1, T2, ..., Tn> { /* ... */ }类参数部分由尖括号(<>)分隔,紧随类名。 It specifies the type parameters (also called type variables) T1, T2, ..., and Tn . 它指定类型参数(也称为类型变量) T1, T2, ..., and Tn

1. So by doing this: 1.因此,请执行以下操作:

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

the type variables D extends BaseUserDAO<T>, T extends BaseUser, V extends CoreUserValidator<D, T> , instruct Java compiler that in order to use CoreUserEndpoint one needs to specify the types. 类型变量D extends BaseUserDAO<T>, T extends BaseUser, V extends CoreUserValidator<D, T> ,指示Java编译器要使用CoreUserEndpoint必须指定类型。

2. Next when you do this: 2.接下来,当您执行此操作时:

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

you use the previously defined type arguments to be used in EntityEndpoint . 您使用在EntityEndpoint使用的先前定义的类型参数。 Now, compiler would look for classes (or interfaces, ...) named D , T and V . 现在,编译器将查找名为DTV类(或接口,...)。

Here comes the part which I am not sure about. 这是我不确定的部分。 If compiler finds them from your declaration for CoreUserEndpoint , then you're trying to force the class to extend from multiple classes, which is not allowed, by doing this: 如果编译器从您的CoreUserEndpoint声明中找到了它们,那么您将试图通过以下方法强制该类从多个类扩展:

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

PS I would higly appreciate any feedback, if what I've written here makes any sence, from experience Java devs. PS:如果我在这里写的内容有任何见识,我将非常感谢经验丰富的Java开发人员的任何反馈。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM