pre*_*oid 5 java spring dependency-injection spring-mvc spring-boot
我的课如下
@Component
public abstract class NotificationCenter {
protected final EmailService emailService;
protected final Logger log = LoggerFactory.getLogger(getClass());
protected NotificationCenter(EmailService emailService) {
this.emailService = emailService;
}
protected void notifyOverEmail(String email, String message) {
//do some work
emailService.send(email, message);
}
}
Run Code Online (Sandbox Code Playgroud)
EmailService是一个@Service,应通过构造函数注入自动连接。
现在,我有一个扩展的类,还NotificationCenter应该自动装配组件
@Service
public class NotificationCenterA extends NotificationCenter {
private final TemplateBuildingService templateBuildingService;
public NotificationCenterA(TemplateBuildingService templateBuildingService) {
this.templateBuildingService = templateBuildingService;
}
}
Run Code Online (Sandbox Code Playgroud)
根据上面的示例,该代码将不会编译,因为抽象类中没有默认的构造函数,NotificationCenter除非我将super(emailService);第一个语句添加到NotificationCenterA构造函数中,但是我没有的实例,emailService并且我也不想填充基数孩子们的田野。
知道解决这种情况的正确方法是什么吗?也许我应该使用场注入?
第一点:
@Component不适合在您将显式实现的抽象类中使用。抽象类不能是组件,因为它是抽象的。
删除它并考虑下一点。
第二点:
我不打算从儿童中填充基础字段。
如果没有 Spring 和 DI,您可以直接在父类中硬编码依赖项,但这是可取的吗?并不真地。它隐藏了依赖关系,也使得切换到任何子类的另一个实现甚至测试变得更加复杂。
因此,正确的方法是在子类中注入依赖项,并在父类构造函数中传递注入的 EmailService :
@Service
public class NotificationCenterA extends NotificationCenter {
private final TemplateBuildingService templateBuildingService;
public NotificationCenterA(TemplateBuildingService templateBuildingService, EmailService emailService) {
super(emailService);
this.templateBuildingService = templateBuildingService;
}
}
Run Code Online (Sandbox Code Playgroud)
并且在父类中只需删除无用的@Component注释即可。
知道处理这种情况的正确方法是什么吗?也许我应该使用现场注入?
并非如此,它只会使您的代码不太可测试/灵活和清晰。
NotificationCenter不是一个真正的类,而是一个抽象类,因此您不能创建它的实例。另一方面,它具有EmailService必须在构造函数中初始化的字段(最终字段!)!设置器在这里不起作用,因为最终字段仅被初始化一次。它是Java,甚至不是Spring。
任何扩展的类都将NotificationCenter 继承字段EmailService,因为此子项“是”通知中心
因此,您必须提供一个构造函数,该构造函数获取电子邮件服务的实例并将其传递给super进行初始化。再次是Java,不是Spring。
public class NotificationCenterA extends NotificationCenter {
private final TemplateBuildingService templateBuildingService;
public NotificationCenterA(EmailService emailService, TemplateBuildingService templateBuildingService) {
super(emailService);
this.templateBuildingService = templateBuildingService;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,spring为您管理bean,它初始化它们并注入依赖项。坦白地说,你写的东西我听不懂:
...作为对NotificationCenterA构造函数的第一条声明,但我没有emailService的实例,也不打算从子级中填充基字段。
但是Spring将仅管理一个NotificationCenterAbean(当然还有EmailService的实现),它不管理抽象类,并且由于Java设置了上述限制(出于某种原因),因此我认为对您问题的直接答案将是:
| 归档时间: |
|
| 查看次数: |
2341 次 |
| 最近记录: |