最佳实践:Spring自动连线、混凝土类和生成器

最佳实践:Spring自动连线、混凝土类和生成器,spring,interface,builder,autowired,concreteclass,Spring,Interface,Builder,Autowired,Concreteclass,我们有一个接口: public interface NotifyService { public void send(); 以及实现它的类 public class EmailNotifyService implements NotifyService { private EmailBuilder _builder; @Autowired PersonRepository _personRepository; ... other Autowired Reposito

我们有一个接口:

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。问题是,在我们应用程序的其他地方,我们都是自动连接接口,而不是类。从我所读到的来看,总的来说这是个好主意。事实上,我已经尝试将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"/>  
既然NotifyService对人员、电子邮件类型和事件数据一无所知,我如何设置这些数据


目前,我们正在web应用程序中使用mailer服务,但理论上,mailer服务应该能够独立工作。不管怎样,我看不出请求范围的bean在这里能帮我什么忙。

Robert你说的自动连接不正确是什么意思?你有什么错误吗

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

您不需要在接口中包含setPerson()、setEmailType()等,但需要将它们自动连接到需要它们的具体类中

但Person似乎不是一个服务,而是一个bean,它保存数据和特定于请求的数据。如果您的应用程序是web应用程序,那么请查看请求作用域代理以注入类似bean的人员


所以您使用的是事务,这就是基于类的注入失败的原因。将代理目标class=“true”添加到
tx:annotation-driven

关于
Person
EmailType
的注入,您必须对bean
EmailNotifyService
执行该操作。在
EmailNotifyService
中,我没有看到定义了任何
Person
EmailType
变量。也请阅读我在上面对Person bean所说的话



你的设计不正确。您不应该将
EmailBuilder
设置为bean,并希望自动连接到
EmailNotifyService
。相反,在
EmailNotifyService
中,您应该有一个方法
send(EmailBuilder)
用于传递动态创建的生成器。

能否显示xml配置文件?嗯。。。好的,我知道如果我想使用一个具体的类,我需要添加“proxy target class=“true”。但是如果我选择使用该界面,我仍然看不到如何分配人员、电子邮件类型和事件信息。EmailNotifyService中没有这些bean的setter,但是有一个接受构建器的构造函数,而构建器拥有所有getter和setter。但是,如果Spring正在使用Autowire和接口实例化该类,如何将构建器传递给EmailNotifyService构造函数呢?请在Spring是EmailNotifyService的对象时从EmailBuilder中删除构建方法。使EmailBuilder也成为一个bean,并自动连接到EmailNotifyService中。也可以在EmailBuilder中自动连接个人和EmailType。但是。。。Person、EmailType和Event中的值在运行时动态分配。目前我们做的是:EmailBuilder=newemailbuilder().recipient(newperson(“Joe”)).type(newemailtype(“normal”).event(newevent(“newevent”)).build()。如果我自动连接构建器及其人员、电子邮件类型和事件,我将如何在运行时动态设置它们?这就是我最后要做的。将接口方法send()更改为send(EmailBuilder)。但我想避免这样做。因为现在我的接口绑定到一个实现。我将返回并使用一个抽象类重试,将“proxy target class=“true”添加到我的配置中,看看它是否有效。非常感谢你的建议。真的。。。但我最初只想在接口中使用send(),不带参数,就像以前一样。但我认为使用Spring Autowired的接口是不可能的。但应该可以使用抽象类并设置“proxy target class=“true””。
@Autowired
@Qualifier("email") // so Spring knows I want to use the EmailNotifyService implementation
NotifyService _notifyService