Java中运行时的依赖项InjeAction
我已经通过JavaCDI阅读了依赖性功能,但到目前为止还不知道如何通过运行时注入类。让我先解释一下情况 假设我有一个JSFWeb应用程序和一个中央电子邮件服务 我正在定义一个接口Java中运行时的依赖项InjeAction,java,jsf,cdi,Java,Jsf,Cdi,我已经通过JavaCDI阅读了依赖性功能,但到目前为止还不知道如何通过运行时注入类。让我先解释一下情况 假设我有一个JSFWeb应用程序和一个中央电子邮件服务 我正在定义一个接口 public interface EmailService { public String sendEmail(Email email); } 接下来,我将使用Smtp具体实现EmailService: public class SmtpEmailServiceImpl implements EmailServic
public interface EmailService {
public String sendEmail(Email email);
}
接下来,我将使用Smtp具体实现EmailService:
public class SmtpEmailServiceImpl implements EmailService {
@Override
public String sendEmail(Email email) {
// concrete implementation using Smtp
}
}
现在在我的web应用程序中,我有了一个JSF支持bean,它应该注入EmailService以便发送电子邮件
public class JSFBackingBean {
// This is the EmailService to be injected
private EmailService emailService;
public String sendEmail(){
emailService.sendEmail(new Email());
}
}
现在让我们假设Smtp服务器因维护而停机。在这种情况下,我想假脱机数据库中的所有电子邮件,并在Smtp服务器启动并运行后处理它们。在这种情况下,我希望第二次实现EmailService:
public class DatabaseEmailService implements EmailService {
@Override
public String sendEmail(Email email) {
// concrete implementation writing the email to a database
}
}
现在我从CDI了解到,我可以使用注释来注入适当的服务实现,但这意味着我必须重新构建和部署我的类,以防我想要更改适当的服务。是否有更好的解决方案,例如使用配置文件,以便在应用程序运行时更改注入
提前谢谢你的回答
Pred好吧,我怀疑您是否希望这样做,以便此电子邮件服务的每个客户端都知道需要关闭邮件服务,即使您使用了注释和实例选择器,例如:
@Inject
private Instance<EmailService> emailServiceInstance;
// few lines down
emailServiceInstance.select(new SmtpLiteral()).get();
@Inject
私有实例;
//几行
emailServiceInstance.select(新的SmtpLiteral()).get();
这就是你用CDI方式做的。我建议的是,此逻辑属于您的
电子邮件服务
,并且它本身会注入对某个DB类的引用,该DB类将消息持久保存到数据库,直到SMTP服务器重新联机。在这种情况下,您可以编写自定义生产者和限定符。不要注入EmailService,而是注入一个“@Failsafe EmailService”
然后写一个制片人
@Produces
@Failsafe
private EmailService failsafeEmailService() {
// here you can check if the Mail Server is available and then decide
// to return the "real" Service or the DB-Queue.
}
您也可以让CDI(直接或通过实例)注入两个备选方案,然后决定传播哪一个,而不是在方法体中创建/查找服务
@Produces
@Failsafe
private EmailService failsafeEmailService(MailServiceBean bean, DBQueue queue) {
return (check_if_mail_server_is_running) ? bean : queue
}
(当然,DBQueue和Bean都必须实现EmailService)。我的想法是向客户机隐藏邮件服务器是否已启动并正在运行。我想做的是,例如,在维护期间更改配置文件以插入DBEmailService而不是SmtpEmailService,并且在Smtp服务器启动并运行后将其更改回SmtpEmailService。客户不会知道邮件服务的技术细节。比如说,我有一个SAP后端,可以从web应用程序下订单。如果SAP因维护而停机,我希望切换到另一个服务实现来缓存传入订单,而不进行重建和depl。我的webappWell,你正在重新启动你的应用程序。我会在这个EmailService中加入操作逻辑,只让您的客户端注入EmailService。谢谢,不一定需要重新启动。如果我使用spring,这将是配置xml中的一个简单更改。难道没有更优雅的方式吗?假设我正在提供一个可以处理数据库或LDAP身份验证的软件。我希望我的客户在安装过程中选择他希望使用的身份验证类型。这需要通过配置屏幕动态地进行,而不是通过构建和部署classesAgreed。CDI不是春天。CDI中最接近您的东西是备选方案,它需要放在beans.xml中。