Spring的@Service逻辑与构建器模式(Builder Pattern)

huangapple go评论103阅读模式
英文:

Spring @Service logic with Builder Pattern

问题

我已经在Spring Boot应用程序中使用构建器模式实现了服务逻辑,代码如下:

  1. @Service
  2. public class EmailServiceImpl implements NotificationService{
  3. private Map<String, Object> emailTemplateContext;
  4. private List<String> recipients;
  5. private String templateName;
  6. private String subjectName;
  7. private List<String> ccRecipients;
  8. public EmailServiceImpl() {
  9. }
  10. private EmailServiceImpl(String templateName, String subjectName, List<String> recipients,
  11. List<String> ccRecipients,
  12. Map<String, Object> emailTemplateContext) {
  13. this.emailTemplateContext = emailTemplateContext;
  14. this.recipients = recipients;
  15. this.templateName = templateName;
  16. this.subjectName = subjectName;
  17. this.ccRecipients = ccRecipients;
  18. }
  19. public static class EmailBuilder {
  20. private Map<String, Object> emailTemplateContext = new HashMap<String, Object>();
  21. private List<String> recipients;
  22. private String templateName;
  23. private String subjectName;
  24. private List<String> ccRecipients;
  25. public EmailBuilder withTemplateName(String templateName) {
  26. this.templateName = templateName;
  27. return this;
  28. }
  29. public EmailBuilder withSubjectName(String subjectName) {
  30. this.subjectName = subjectName;
  31. return this;
  32. }
  33. public EmailBuilder withTemplateContextValues(String key, String value) {
  34. this.emailTemplateContext.put(key, value);
  35. return this;
  36. }
  37. public EmailBuilder withTemplateContextValues(String key, List<String> value) {
  38. this.emailTemplateContext.put(key, value);
  39. return this;
  40. }
  41. public EmailBuilder withRecipients(List<String> recipients) {
  42. this.recipients = recipients;
  43. return this;
  44. }
  45. public EmailBuilder withCCRecipients(List<String> ccRecipients) {
  46. this.ccRecipients = ccRecipients;
  47. return this;
  48. }
  49. public EmailServiceImpl build() {
  50. return new EmailServiceImpl(templateName, subjectName, recipients, ccRecipients, emailTemplateContext);
  51. }
  52. }
  53. public void send() {
  54. // 实现电子邮件发送逻辑
  55. }
  56. }

然后,它将被注入到另一个类中,类似于以下方式:

  1. public class EmailSender {
  2. private EmailBuilder emailBuilder;
  3. EmailSender(EmailBuilder emailBuilder) {
  4. this.emailBuilder = emailBuilder;
  5. }
  6. public void sendEmail() {
  7. this.emailBuilder
  8. .withRecipients(executionRunBO.getEmailRecipients().stream().map(email -> email.getEmail())
  9. .collect(Collectors.toList()))
  10. .withSubjectName("Reports Draft ").withTemplateName("/emails/reports.ftlh")
  11. .withTemplateContextValues("userName", "TestUser").build().send();
  12. }
  13. }

关于使用构建器模式和Spring的一些问题:

  1. 由于@Service注释的构造函数是私有的,Spring框架无法初始化该bean类。为了避免获得初始化异常,我将构造函数设置为了public,但这不是构建器模式的正确使用方式。如何正确地在Spring框架中实现构建器模式?

  2. 如何在服务类之外调用EmailServiceImpl类的EmailBuilder?在我的示例中,我已将EmailBuilder作为构造函数参数注入,然后Spring框架抛出以下错误:

    1. 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.

  1. @Service
  2. public class EmailServiceImpl implements NotificationService{
  3. private Map&lt;String, Object&gt; emailTemplateContext;;
  4. private List&lt;String&gt; recipients;
  5. private String templateName;
  6. private String subjectName;
  7. private List&lt;String&gt; ccRecipients;
  8. public EmailServiceImpl() {
  9. }
  10. private EmailServiceImpl(String templateName, String subjectName, List&lt;String&gt; recipients,
  11. List&lt;String&gt; ccRecipients,
  12. Map&lt;String, Object&gt; emailTemplateContext) {
  13. this.emailTemplateContext = emailTemplateContext;
  14. this.recipients = recipients;
  15. this.templateName = templateName;
  16. this.subjectName = subjectName;
  17. this.ccRecipients = ccRecipients;
  18. }
  19. public static class EmailBuilder {
  20. private Map&lt;String, Object&gt; emailTemplateContext = new HashMap&lt;String, Object&gt;();
  21. private List&lt;String&gt; recipients;
  22. private String templateName;
  23. private String subjectName;
  24. private List&lt;String&gt; ccRecipients;
  25. public EmailBuilder withTemplateName(String templateName) {
  26. this.templateName = templateName;
  27. return this;
  28. }
  29. public EmailBuilder withSubjectName(String subjectName) {
  30. this.subjectName = subjectName;
  31. return this;
  32. }
  33. public EmailBuilder withTemplateContextValues(String key, String value) {
  34. this.emailTemplateContext.put(key, value);
  35. return this;
  36. }
  37. public EmailBuilder withTemplateContextValues(String key,List&lt; String&gt; value) {
  38. this.emailTemplateContext.put(key, value);
  39. return this;
  40. }
  41. public EmailBuilder withRecipients(List&lt;String&gt; recipients) {
  42. this.recipients = recipients;
  43. return this;
  44. }
  45. public EmailBuilder withCCRecipients(List&lt;String&gt; ccRecipients) {
  46. this.ccRecipients = ccRecipients;
  47. return this;
  48. }
  49. public EmailServiceImpl build() {
  50. return new EmailServiceImpl(templateName, subjectName, recipients, ccRecipients, emailTemplateContext);
  51. }
  52. }
  53. public void send() {
  54. // implement email send logic
  55. }
  56. }

Then this will be injected in another class something like below

  1. public class EmailSender{
  2. private EmailBuilder emailBuilder;
  3. EmailSender(EmailBuilder emailBuilder){
  4. this.emailBuilder=emailBuilder;
  5. }
  6. public void sendEmail(){
  7. this.emailBuilder
  8. .withRecipients(executionRunBO.getEmailRecipients().stream().map(email -&gt; email.getEmail())
  9. .collect(Collectors.toList()))
  10. .withSubjectName(&quot;Reports Draft &quot;).withTemplateName(&quot;/emails/reports.ftlh&quot;)
  11. .withTemplateContextValues(&quot;userName&quot;, &quot;TestUser&quot;).build().send();
  12. }
  13. }

There are few questions related to the Builder pattern with Spring.

  1. 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?

  2. 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。

  1. public class Email {
  2. private Map<String, Object> emailTemplateContext;
  3. private List<String> recipients;
  4. private String templateName;
  5. private String subjectName;
  6. private List<String> ccRecipients;
  7. private Email(String templateName, String subjectName, List<String> recipients,
  8. List<String> ccRecipients,
  9. Map<String, Object> emailTemplateContext) {
  10. this.emailTemplateContext = emailTemplateContext;
  11. this.recipients = recipients;
  12. this.templateName = templateName;
  13. this.subjectName = subjectName;
  14. this.ccRecipients = ccRecipients;
  15. }
  16. public static class EmailBuilder {
  17. // 你的构建器代码,只需构建Email
  18. }
  19. }

然后创建一个用于发送电子邮件的服务。

  1. @Service
  2. public class EmailServiceImpl implements NotificationService {
  3. public void sendEmail(Email email) {
  4. }
  5. }

像这样调用它

  1. emailService.sendEmail(new Email.EmailBuilder().build());

没有必要为EmailEmailBuilder创建一个@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.

  1. public class Email {
  2. private Map&lt;String, Object&gt; emailTemplateContext;
  3. private List&lt;String&gt; recipients;
  4. private String templateName;
  5. private String subjectName;
  6. private List&lt;String&gt; ccRecipients;
  7. private Email(String templateName, String subjectName, List&lt;String&gt; recipients,
  8. List&lt;String&gt; ccRecipients,
  9. Map&lt;String, Object&gt; emailTemplateContext) {
  10. this.emailTemplateContext = emailTemplateContext;
  11. this.recipients = recipients;
  12. this.templateName = templateName;
  13. this.subjectName = subjectName;
  14. this.ccRecipients = ccRecipients;
  15. }
  16. public static class EmailBuilder {
  17. // your builder code, just build the Email
  18. }
  19. }

And then have a service to send emails.

  1. @Service
  2. public class EmailServiceImpl implements NotificationService {
  3. public void sendEmail(Email email) {
  4. }
  5. }

Call it like this

  1. emailService.sendEmail(new Email.EmailBuilder().build());

There is no need to create a @service from the Email and EmailBuilder.

huangapple
  • 本文由 发表于 2020年8月24日 16:50:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63557676.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定