我们有一个界面:
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如何在这里帮助我。
罗伯特,你说没有正确自动装配是什么意思?你有任何错误吗?
通常接口和类自动接线都可以在Spring中工作,除非您配置了一些自动代理示例@Transactional
。
您不需要在接口中使用setPerson()、setEmailType()等,而是在需要它们的具体类中自动安装它们。
但是Person似乎不是一个服务,而是一个bean,它保存数据并特定于请求。如果您的是Web应用程序,那么请查看请求范围代理以像bean一样注入Person。
所以您正在使用事务,这就是基于类的注入失败的原因。将proxy-target et-class="true"
添加到tx:注解驱动
。
关于您对Person
和EmailType
的注入,那么您必须对beanEmailNotifyService
执行此操作。在EmailNotifyService
中,我没有看到任何定义的Person
或EmailType
变量。还请阅读我上面关于Person bean的内容。
您的设计不正确。您不应该将EmailBuilder
设为bean并查看自动连接到EmailNotifyService
。相反,在EmailNotifyService
中,您应该有一个方法send(EmailBuilder builder)
,您可以在其中传递您在某处动态创建的构建器。