提问者:小点点

最佳实践:Spring Autowed、具体类和Builder


我们有一个界面:

public interface NotifyService {

  public void send();

还有一个实现它的类

public class EmailNotifyService implements NotifyService {

  private EmailBuilder _builder;

  @Autowired
  PersonRepository _personRepository;

  ... other Autowired Repositories ...

  public EmailNotifyService(EmailBuilder builder) {
   this._builder = builder;
  }

  public void send() {
    // send mail using _builder.getRecipient().getEmailAddress(), etc.
  }

我们曾经使用构建器实例化EmailNotifyService:

public class EmailBuilder {

  private Person _recipient;

  private EmailType _type;

  private Event _event;

  public EmailNotifyService build() {
    return new EmailNotifyService(this);
  }

  public EmailBuilder recipient(Person recipient) {
    this._recipient = recipient;
    return this;
  }

…等等。但是现在,我们没有使用build()来创建一个新的EmailNotifyService,而是尝试在Spring中使用Autowire。问题是在我们应用程序的其他地方,我们都是自动装配接口,而不是类。从我所读到的来看,这总体上是个好主意。事实上,我尝试过将NotifyService重写为一个抽象类,然后让EmailNotifyService对其进行扩展。但是Spring没有正确地自动装配它,它没有像为接口那样创建代理,并且我所有的自动装配字段都是空的。

所以我们似乎被困在自动装配NotifyService接口上了。好吧。我想不通的是——我如何才能将我用来分配给构建器的数据——人员、电子邮件类型和事件——获取到Spring自动装配接口中?

我想我可以将接口定义更改为具有setPerson()、setEmailType()等。,但是除了非常丑陋之外,它首先违背了使用接口的目的。不同的NotifyService(例如WebServiceNotifyService或RestNotifyService)晚上不需要这些信息。

有什么优雅的、最佳实践的方法来做到这一点吗?

谢谢。

编辑

我正在使用注释,很少使用xml。我也在使用事务管理,这可能解释了为什么抽象类没有正确自动装配?这是我在xml中唯一的永久信息:

<context:annotation-config />  
<context:component-scan base-package="com.myco.myapp" />  
<tx:annotation-driven transaction-manager="transactionManager"/>  

当我说“自动装配无法正常工作”时,我的意思是,当我尝试自动装配抽象类时,Spring似乎没有像为接口那样创建代理,并且我的EmailNotifyService中的所有自动装配字段都为空。当我使用接口时,所有自动装配字段都正确连接。

但我的主要问题是,我曾经显式地使用一个具体类,使用构建器直接创建一个新的EmailNotifyService(),并向它传递信息——Person、EmailType和Event。这些只是普通的bean。在EmailNotifyService中没有它们的setter/getter,但有EmailBuilder,它曾经存在于EmailNotifyService中。

但是现在我使用的是NotifyService接口,它对Person、EmailType或Event一无所知。但是我需要这些信息才能让EmailNotifyService工作。

所以我的问题是,如果我使用Spring像这样自动安装我的EmailNotifyService:

@Autowired
@Qualifier("email") // so Spring knows I want to use the EmailNotifyService implementation
NotifyService _notifyService

如何设置Person、EmailType和Event数据,因为NotifyService对它们一无所知?

目前我们在Web应用程序中使用邮件服务,但理论上邮件服务应该能够独立工作。无论如何,我不明白请求范围的bean如何在这里帮助我。


共1个答案

匿名用户

罗伯特,你说没有正确自动装配是什么意思?你有任何错误吗?

通常接口和类自动接线都可以在Spring中工作,除非您配置了一些自动代理示例@Transactional

您不需要在接口中使用setPerson()、setEmailType()等,而是在需要它们的具体类中自动安装它们。

但是Person似乎不是一个服务,而是一个bean,它保存数据并特定于请求。如果您的是Web应用程序,那么请查看请求范围代理以像bean一样注入Person。

所以您正在使用事务,这就是基于类的注入失败的原因。将proxy-target et-class="true"添加到tx:注解驱动

关于您对PersonEmailType的注入,那么您必须对beanEmailNotifyService执行此操作。在EmailNotifyService中,我没有看到任何定义的PersonEmailType变量。还请阅读我上面关于Person bean的内容。

您的设计不正确。您不应该将EmailBuilder设为bean并查看自动连接到EmailNotifyService。相反,在EmailNotifyService中,您应该有一个方法send(EmailBuilder builder),您可以在其中传递您在某处动态创建的构建器。