英文:
Spring @Service logic with Builder Pattern
问题
我已经在Spring Boot应用程序中使用构建器模式实现了服务逻辑,代码如下:
@Service
public class EmailServiceImpl implements NotificationService{
private Map<String, Object> emailTemplateContext;
private List<String> recipients;
private String templateName;
private String subjectName;
private List<String> ccRecipients;
public EmailServiceImpl() {
}
private EmailServiceImpl(String templateName, String subjectName, List<String> recipients,
List<String> ccRecipients,
Map<String, Object> emailTemplateContext) {
this.emailTemplateContext = emailTemplateContext;
this.recipients = recipients;
this.templateName = templateName;
this.subjectName = subjectName;
this.ccRecipients = ccRecipients;
}
public static class EmailBuilder {
private Map<String, Object> emailTemplateContext = new HashMap<String, Object>();
private List<String> recipients;
private String templateName;
private String subjectName;
private List<String> ccRecipients;
public EmailBuilder withTemplateName(String templateName) {
this.templateName = templateName;
return this;
}
public EmailBuilder withSubjectName(String subjectName) {
this.subjectName = subjectName;
return this;
}
public EmailBuilder withTemplateContextValues(String key, String value) {
this.emailTemplateContext.put(key, value);
return this;
}
public EmailBuilder withTemplateContextValues(String key, List<String> value) {
this.emailTemplateContext.put(key, value);
return this;
}
public EmailBuilder withRecipients(List<String> recipients) {
this.recipients = recipients;
return this;
}
public EmailBuilder withCCRecipients(List<String> ccRecipients) {
this.ccRecipients = ccRecipients;
return this;
}
public EmailServiceImpl build() {
return new EmailServiceImpl(templateName, subjectName, recipients, ccRecipients, emailTemplateContext);
}
}
public void send() {
// 实现电子邮件发送逻辑
}
}
然后,它将被注入到另一个类中,类似于以下方式:
public class EmailSender {
private EmailBuilder emailBuilder;
EmailSender(EmailBuilder emailBuilder) {
this.emailBuilder = emailBuilder;
}
public void sendEmail() {
this.emailBuilder
.withRecipients(executionRunBO.getEmailRecipients().stream().map(email -> email.getEmail())
.collect(Collectors.toList()))
.withSubjectName("Reports Draft ").withTemplateName("/emails/reports.ftlh")
.withTemplateContextValues("userName", "TestUser").build().send();
}
}
关于使用构建器模式和Spring的一些问题:
-
由于
@Service
注释的构造函数是私有的,Spring框架无法初始化该bean类。为了避免获得初始化异常,我将构造函数设置为了public,但这不是构建器模式的正确使用方式。如何正确地在Spring框架中实现构建器模式? -
如何在服务类之外调用
EmailServiceImpl
类的EmailBuilder
?在我的示例中,我已将EmailBuilder
作为构造函数参数注入,然后Spring框架抛出以下错误:required a bean of type '...EmailServiceImpl$EmailBuilder' that could not be found.
请帮我澄清这些问题。
英文:
I have implemented service logic using builder pattern like below in a Spring boot application.
@Service
public class EmailServiceImpl implements NotificationService{
private Map<String, Object> emailTemplateContext;;
private List<String> recipients;
private String templateName;
private String subjectName;
private List<String> ccRecipients;
public EmailServiceImpl() {
}
private EmailServiceImpl(String templateName, String subjectName, List<String> recipients,
List<String> ccRecipients,
Map<String, Object> emailTemplateContext) {
this.emailTemplateContext = emailTemplateContext;
this.recipients = recipients;
this.templateName = templateName;
this.subjectName = subjectName;
this.ccRecipients = ccRecipients;
}
public static class EmailBuilder {
private Map<String, Object> emailTemplateContext = new HashMap<String, Object>();
private List<String> recipients;
private String templateName;
private String subjectName;
private List<String> ccRecipients;
public EmailBuilder withTemplateName(String templateName) {
this.templateName = templateName;
return this;
}
public EmailBuilder withSubjectName(String subjectName) {
this.subjectName = subjectName;
return this;
}
public EmailBuilder withTemplateContextValues(String key, String value) {
this.emailTemplateContext.put(key, value);
return this;
}
public EmailBuilder withTemplateContextValues(String key,List< String> value) {
this.emailTemplateContext.put(key, value);
return this;
}
public EmailBuilder withRecipients(List<String> recipients) {
this.recipients = recipients;
return this;
}
public EmailBuilder withCCRecipients(List<String> ccRecipients) {
this.ccRecipients = ccRecipients;
return this;
}
public EmailServiceImpl build() {
return new EmailServiceImpl(templateName, subjectName, recipients, ccRecipients, emailTemplateContext);
}
}
public void send() {
// implement email send logic
}
}
Then this will be injected in another class something like below
public class EmailSender{
private EmailBuilder emailBuilder;
EmailSender(EmailBuilder emailBuilder){
this.emailBuilder=emailBuilder;
}
public void sendEmail(){
this.emailBuilder
.withRecipients(executionRunBO.getEmailRecipients().stream().map(email -> email.getEmail())
.collect(Collectors.toList()))
.withSubjectName("Reports Draft ").withTemplateName("/emails/reports.ftlh")
.withTemplateContextValues("userName", "TestUser").build().send();
}
}
There are few questions related to the Builder pattern with Spring.
-
Since @service constructor is private Spring framework can not initiate the bean class.To avoid getting initialization exception i have made constructor to public but it is not the builder pattern.So how do i implement builder pattern correctly with Spring framework?
-
How do i call the EmailServiceImpl class's EmailBuilder outside from the service class? Since in my examples i have injected EmailBuilder as a constructor argument then Spring framework throws that
> required a bean of type '...EmailServiceImpl$EmailBuilder' that could
> not be found.
Please help me to clarify those things.
答案1
得分: 1
你在这里将许多功能混在一起。我会让这个过程更加简化。
我会创建一个dto类Email
,而不是一个Spring bean。
public class Email {
private Map<String, Object> emailTemplateContext;
private List<String> recipients;
private String templateName;
private String subjectName;
private List<String> ccRecipients;
private Email(String templateName, String subjectName, List<String> recipients,
List<String> ccRecipients,
Map<String, Object> emailTemplateContext) {
this.emailTemplateContext = emailTemplateContext;
this.recipients = recipients;
this.templateName = templateName;
this.subjectName = subjectName;
this.ccRecipients = ccRecipients;
}
public static class EmailBuilder {
// 你的构建器代码,只需构建Email
}
}
然后创建一个用于发送电子邮件的服务。
@Service
public class EmailServiceImpl implements NotificationService {
public void sendEmail(Email email) {
}
}
像这样调用它
emailService.sendEmail(new Email.EmailBuilder().build());
没有必要为Email
和EmailBuilder
创建一个@service
。
英文:
You are mixing a lot of functionality together here. I would make this more streamlined.
I would create a dto class Email
, not a Spring bean.
public class Email {
private Map<String, Object> emailTemplateContext;
private List<String> recipients;
private String templateName;
private String subjectName;
private List<String> ccRecipients;
private Email(String templateName, String subjectName, List<String> recipients,
List<String> ccRecipients,
Map<String, Object> emailTemplateContext) {
this.emailTemplateContext = emailTemplateContext;
this.recipients = recipients;
this.templateName = templateName;
this.subjectName = subjectName;
this.ccRecipients = ccRecipients;
}
public static class EmailBuilder {
// your builder code, just build the Email
}
}
And then have a service to send emails.
@Service
public class EmailServiceImpl implements NotificationService {
public void sendEmail(Email email) {
}
}
Call it like this
emailService.sendEmail(new Email.EmailBuilder().build());
There is no need to create a @service
from the Email
and EmailBuilder
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论