Seb*_*mba 2 java factory factory-pattern cdi jboss-weld
我想向我们的项目介绍CDI(Weld),现在手动构建的对象遇到了一些麻烦.
所以我们有一些实现IReport接口的类,它有一个应该注入的字段.因为所有这些类是由产生这是在运行时零ReportFactory一类ReportController.
private Map<String,Object> generateReport(ReportInfo ri, ...) {
// some input validation
IReport report = ReportControllerFactory.getReportInstance( ri.getClassName() );
// ...
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以将@Produces注释与另一个自定义注释一起使用ReportControllerFactory,但是如何在一个方法中使用@Injectfor只能在完成一些验证之后创建的变量?我将如何提交参数?构造时对象是未知的.ri.getClassName()riReportController
非常感谢你!
亲切的问候,塞巴斯蒂安
编辑于2011年7月8日(10:00):
ReportFactory类:
public static IReport getReportInstance( String className ) throws ReportException {
IReport report = null;
try {
Class<?> clazz = Class.forName( className );
report = (IReport) clazz.newInstance();
}
catch ( Exception e ) { … }
return report;
}
Run Code Online (Sandbox Code Playgroud)
编辑2(选择正确的报告实施)
报告实例由从JSF前端到ReportController的一些路径选择.ManagedBean调用一个会话bean,它有几种方法,具体取决于按下哪个按钮.所有这些方法都设置了报告名称并调用了更通用的方法sendOrGetReport.此方法从数据库中选择指定报告的唯一键,并决定是发送电子邮件还是立即发送报告.我们假设应该交付.
然后ReportController发挥作用.他ReportInfo根据上述方法提供的唯一键和其他信息获取对象,并调用它ReportFactory来创建类型报告ri.getClassName().
好吗,对吧?我认为整个部分可能需要一些重构.如果您没有看到任何简单的位置,我会跳过@Inject报告实现并对该资源执行JDNI查找.
小智 12
为了动态创建正确的报告类,对接受的答案进行小的更改将解决问题.解决方案是Instance <...>为您提供了某种类型的所有bean的列表.不需要生成注释.
创建一个工厂类,可以在运行时在注入的实例之间进行选择
public class ReportFactory {
@Inject Instance<IReport> availableReports;
public IReport createReport(String type) {
for (IReport report: availableReports) {
if (report.getType().equals(type)) { //or whatever test you need
return report;
}
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
现在需要动态选择报告的类可以使用此工厂.
public class ReportCreator {
@Inject
private ReportFactory reportFactory;
public void createReport(String type) {
IReport report = reportFactory.createReport(type);
report.execute();
}
}
Run Code Online (Sandbox Code Playgroud)
CDI(和其他DI框架)为了管理依赖关系而背后的想法是接管对托管bean生命周期的控制.这意味着 - 除其他外 - 如果您希望托管bean由容器管理,则不能干扰托管bean的创建.
当然这并不意味着你的场景无法解决,你只需稍微改变你的观点;-)
这个想法是使用托管bean(显然),但让你自己的逻辑决定所有可用实例的哪个实例是正确的.
...
@Inject Instance<IReport> availableReports;
...
@Produces
public IReport createReport() {
IReport result;
for (IReport report: availableReports) {
// choose correct instance, you might want to query the injection
// point or any attached qualifier a bit more in order to
// determine which is the correct instance
if ...
result = report;
...
}
return result;
}
...
Run Code Online (Sandbox Code Playgroud)
随着你喜欢的各种各样的豆类IReport
public class AReport implements IReport {
...
@Inject
...
}
public class BReport implements IReport {
...
@Inject
...
}
Run Code Online (Sandbox Code Playgroud)
像这样的自动化用法
public class MyStuff {
...
@Inject
IReport myReport;
...
}
Run Code Online (Sandbox Code Playgroud)
如果我没有误解你的问题,这应该会带给你前进 - 随时发布更多问题/评论.
更新:
如果这样的东西符合您的要求,那么一切都可能很简单:
@AReport
public class AReport implements IReport {
...
@Inject
...
}
@BReport
public class BReport implements IReport {
...
@Inject
...
}
Run Code Online (Sandbox Code Playgroud)
有了这样的用法
public class MyStuff {
...
@Inject
@AReport
IReport myAReport;
...
@Inject
@BReport
IReport myBReport;
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10718 次 |
| 最近记录: |