最佳实践:Spring Autowired,具体类和Builder

时间:2013-04-15 21:58:33

标签: spring interface builder autowired concreteclass

我们有一个界面:

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,而是尝试使用Autowire和Spring。问题是我们的应用程序中的其他任何地方,我们都是Autowiring接口,而不是类。从我读过的内容来看,这是一个好主意。事实上,我已经尝试将NotifyService重写为Abstract类,然后让EmailNotifyService扩展它。但Spring并没有正确地自动装配它,它没有像接口那样创建代理,而且我的所有自动连接字段都是空的。

所以看起来我们仍然坚持使用NotifyService接口进行自动装配。精细。我无法理解的是 - 如何将我用于分配构建器的数据(Person,EmailType和Event)转换为Spring Autowired接口?

我想我可以将接口定义改为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(PersonRepository,其他......)为空。当我使用接口时,所有自动连接字段都正确连接。

但我的主要问题是我曾经使用构建器直接创建一个新的EmailNotifyService(),然后传递信息 - Person,EmailType和Event。这些只是普通的豆子。在EmailNotifyService中没有针对它们的setter / getters,但有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对它们一无所知?

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

1 个答案:

答案 0 :(得分:0)

罗伯特,你的意思是没有正确自动装配?你收到任何错误吗?

通常接口和类自动布线都在Spring中工作,除非你有一些autoproxy配置的例子@Transactional

您不需要在界面中使用setPerson(),setEmailType()等,而是将它们自动装配在需要它们的具体类中。

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


因此,您正在使用交易,这就是基于类注入失败的原因。将proxy-target-class="true"添加到tx:annotation-driven

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


您的设计不正确。你不应该让EmailBuilder成为一个bean,并且希望自动装配到EmailNotifyService。相反,在EmailNotifyService中,您应该有一个方法send(EmailBuilder builder),您可以在其中传递您在动态创建的构建器。