CDI是最近对Java EE最好的补充之一。 该观点在用户和集成商之间广泛共享。 当前版本的CDI 1.2于2014年4月发布。现在,在2015年中期,我们将面对CDI 2.0规范的早期草案。 CDI 2.0将在Java 8和更高版本上运行。
最终版本计划于2016年发布,该路线图包含几个有趣的项目:
- 将API分为Java SE和Java SE两部分:拆分API是支持微服务移动的重要步骤。 从几行中的每个
main()
引导CDI。 - 异步事件和优先事件允许控制事件观察者的排序和异步传递事件
- JDK 8:CDI 1.x针对Java 1.6及更高版本。 Java 8进行了许多改进,并有助于简化CDI的API。
- CDI允许从起源开始扩展。 SPI非常适合使用DeltaSpike,Spring Data,Camel,CDI度量标准等框架来增强CDI。 CDI 2.0旨在改善对扩展的支持
- 你知道吗? CDI大量使用AOP来实现非常舒适的使用。 所有常规范围(例如RequestScoped,ConversationScoped,SessionScoped和ApplicationScoped)都使用代理来查找上下文实例。 但是一个极限规范是,CDI不允许在本地方法调用上进行自我注入或拦截。 AOP软件包将解决这些问题并改进规范的某些部分。
但是,让我们看一下CDI 2.0 EDR的API(早期草案审查),它是新的且值得注意的 。
异步事件
异步事件是CDI用户希望列表上的第一项。 该问题在2011年初提出,是CDI 2.0的重点之一。 为了启用异步处理的事件并且不通过引入异步性破坏现有代码,需要进行大量热烈讨论。 当前草案需要双端激活
public class AsyncEvents {
@Inject
private Event<MyEventPayload> event;
public void triggerEvent() {
event.fireAsync(new MyEventPayload());
}
public void asyncEventObserver(@ObservesAsync
MyEventPayload payload) {
System.out.println("Yay, I'm called async!");
}
public void eventObserver(@Observes MyEventPayload payload) {
System.out.println("Yay, I'm called too. " +
"Other @Observes are notified in order.");
}
public static class MyEventPayload {
}
}
可以通过对启用了异步功能的观察者的异步处理来触发事件。 使用@Observes
观察者也会在调用线程中得到通知。 可以使用调用fireAsync
时返回的CompletionStage
跟踪异步事件观察器的CompletionStage
fireAsync
。
当事件处理处于活动状态时,异步事件观察器可以在上下文Bean实例上进行操作。 默认情况下,启用的范围是@RequestScoped
和@ApplicationScoped
。 该@SessionScoped
被排除variuous原因。 只要考虑一下会话在事件处理过程中结束时的行为方式即可。 在上下文实例中修改事件有效负载或数据时,用户应注意效果。 CDI不会强制事件有效负载保持不变,但强烈建议您避免由于并发而导致竞争情况。
CDI容器负责提供多线程基础结构。 有时,您想提供一个自己的执行程序来控制并发级别或包装异步调用。 fireAsync
方法允许为每个调用指定单独的执行程序。
private ExecutorService executor;
@Inject
private Event<MyEventPayload> event;
@PostConstruct
public void postConstruct() {
int threads = Runtime.getRuntime().availableProcessors();
executor = new ThreadPoolExecutor(threads, threads, 1,
TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
}
@PreDestroy
public void preDestroy() {
executor.shutdown();
}
public void triggerEventWithExecutor() {
event.fireAsync(new MyEventPayload(), executor);
}
上面的示例创建/销毁执行器。 您可以将CDI管理的执行器与生产者方法( @Produces
)结合使用,并在需要的地方@Inject
。 CDI很酷,是吗?
异步事件将仍然是一个热门话题,这肯定不是其最终形式。
有序事件观察者
在CDI 1.2中,使用事件观察器时的通知顺序是不可预测的。 在2.0中,这将发生变化。
public class PrioritizedEvents {
@Inject
private Event<MyEventPayload> event;
public void trigger() {
event.fire(new MyEventPayload());
}
public void observeBeforeOtherObservers(@Observes
@Priority(Interceptor.Priority.APPLICATION + 499) MyEventPayload payload) {
System.out.println("Notified before all other observers");
}
public void observeAfterOtherObservers(@Observes
@Priority(Interceptor.Priority.APPLICATION + 501) MyEventPayload payload) {
System.out.println("Notified after all other observers");
}
public static class MyEventPayload {
}
}
事件观察者的顺序可以通过应用@Priority
注释来影响。 为什么受到影响却不受控制?
这个问题的答案更长一些,您需要了解CDI的类型安全解析部分。 事件观察者是根据其事件有效负载类型选择的。 事件观察者可以观察不同的类型,接口,类,子类型,合格和不合格类型。 通过使用Event
或BeanManager
API,可以在触发事件时选择事件观察器。 您可以通过使用类型或其子类型来通知另一组事件观察者。 因此,没有可用的全局事件观察者顺序,这导致我们使用@Priority
批注。
通过应用@Priority
可以提前通知某些事件观察者,并在以后通知它们。 默认值为Interceptor.Priority.APPLICATION + 500
,结果为2500
。 这是所有不带有@Priority
批注的事件观察器的默认值。
仔细观察@Priority
发现,它仅适用于当前类型。 这将更改,直到CDI 2.0最终确定。
Java SE的CDI
JavaSE的CDI从一开始就可用,或者我这样说:您可以在JavaSE中启动Weld和OpenWebBeans,而无需JavaEE容器。 CDI 2.0仅指定了以标准方式引导CDI容器的标准方法。 这是我个人的最爱。
public class CDIJumpStart {
public static void main(String[] args) {
try(CDI<Object> cdi = CDI.getCDIProvider().initialize()) {
cdi.select(MyApp.class).get().runMyApplication();
}
}
private static class MyApp{
public void runMyApplication(){
// ...
}
}
}
该代码将启动CDI容器并调用一种方法来运行您的应用程序。 应用程序完成后,将使用try-with-resources
模式关闭容器。 用来启动一个独立的,可能是微服务式应用程序的代码比Spring Boot长两行。 与Spring或Dropwizard的主要区别在于生态系统,我找不到现成的嵌入式Tomcat的集成。 我猜想,JavaSE的CDI成为真正的微服务框架之类的替代品要花费一些时间。
结论
CDI 2.0 EDR只是正在进行的JSR365工作的很小的成果。 有很多问题需要讨论和说明。 JBoss的Weld团队会为规范的发展而努力,并会在将来的某个地方提出RI。 CDI是一个热门话题,并且对于Java EE和SE仍然非常有吸引力。 请继续关注并遵循CDI 2.0
与CDI规范联系:
- Spec网站: http : //www.cdi-spec.org/
- GitHub: https : //github.com/cdi-spec/cdi
- 主要邮件列表: https : //lists.jboss.org/mailman/listinfo/cdi-dev
- CDI 2.0 JCP页面: http : //jcp.org/en/jsr/summary? id = 365
- IRC:irc://freenode.net/#cdi-dev
- 推特:@cdispec
- Google+: https : //plus.google.com/+CdiSpecOrgPage/posts
翻译自: https://www.javacodegeeks.com/2015/09/a-look-on-cdi-2-0-edr1.html