[英]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
. 现在,编译器将查找名为D
, T
和V
类(或接口,...)。
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.