cdi-api_CDI概述-第2部分

cdi-api

在CDI的前一部分 ,我们看到了一些注入,限定词和范围。 现在,该浏览更多高级功能了。

生产者

前面的示例无法解决我们所有的用例。 其中一些包括:

  • 注入随机值
  • 注入上下文相关值
  • 通常,不能将注入过程缩小到简单的new()

这些暗示着一个非常著名的模式,即工厂。 工厂在JSR-299中作为生产者实施。

让我们举一个简单的例子,从数据源注入连接。 获取连接的代码或者通过与数据库的直接连接来创建它,或者从数据源池中检索它。 在最新情况下,以下代码将适用:

public@interfaceFromDataSource{}

publicclassConnectionProducer{

  @Produces@FromDataSource
  publicConnectiongetConnection()throwsException{
    Contextctx=newInitialContext();
    // Read the data source name from web.xml
    Stringname=...
    DataSourceds=(DataSource)ctx.lookup(name);
    returnds.getConnection();
  }
}

拦截器

使用Java EE 6,无需AOP就可以利用AOP的功能。 像前面的示例一样,使用拦截器非常简单。 共有3个步骤。 让我们实现一个简单的计时器,以进行基准测试。

第一步是拦截器的声明。 为此,只需使用@InterceptorBinding

@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD,TYPE})
public@interfaceBenchmarkable{}

第二步是拦截器实现。 它使用`@Interceptor批注以及先前定义的批注:

@Benchmarkable@Interceptor
publicclassBenchmarkInterceptor{

  @AroundInvoke
  publicObjectlogPerformance(InvocationContextic)throwsException{
    longstart=System.currentTimeMillis();
    Objectvalue=ic.proceed();
    System.out.println(System.currentTimeMillis()-start);
    returnvalue;
  }
}

注意:

  • @AroundInvoke注释的方法返回一个Object
  • 它使用InvocationContext类型的参数

最后一步是在`WEB-INF / beans.xml中声明此类拦截器,因为默认情况下拦截器已停用。

<?xml version="1.0" encoding="UTF-8"?>
<beansxmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
  <interceptors>
    <class> ch.frankel.blog.weld.BenchmarkInterceptor </class>
  </interceptors>
</beans>

bean.xml还告诉容器如何在拦截器不止一个的情况下对其进行排序。

还有另外两个拦截器类型, @PostConstruct@AroundTimeout (对于EJB)。

装饰工

装饰器,您猜怎么着,实现装饰器设计模式 。 它们与拦截器非常相似,但有两个有趣的区别:

  • 装饰器必须实现正在装饰的接口(而且可以是抽象的,因此不必实现方法)
  • 装饰器可以引用其装饰的对象。 通过注射完成

与拦截器一样,必须将它们在beans.xml文件中引用才能被激活。 让我们以一个简单的示例为例,创建一个接口,该接口的约定是返回对象HTML表示形式:

publicinterfaceHtmlable{
 StringtoHtml();
}

现在,我需要一个知道其HTML表示形式的日期类。 我知道设计很糟糕,但请耐心等待。

publicclassHtmlDateextendsDateimplementsHtmlable{
  publicStringtoHtml(){
    returntoString();
  }
}

如果我想要一个将HTML放入<strong>标记内的装饰器,请按照以下方式操作:

@Decorator
publicclassStrongDecoratorimplementsHtmlable{

  @Inject@Delegate@Any
  privateHtmlablehtml;

  publicStringtoHtml(){
    return"<strong>"+html.toHtml()+"</strong>";
  }
}

观察者

CDI还实现了Observer设计模式 ,从而最终在Java EE平台上启用了简单的事件驱动开发范例。 它的基础是事件类型。 事件类型是简单的POJO。

Observer也是POJO:为了在事件触发时调用Observer的方法,只需添加正确的事件类型的参数,并使用@Observes对其进行注释:

publicclassEventObserverService{

  publicvoidafterPostEvent(@ObservesPostEventevent){
    ...// Do what must be done
  }
}

另一方面,事件生产者应具有参数javax.enterprise.Event相同事件类型的javax.enterprise.Event类型的属性。 为了触发事件,请使用事件实例调用event.fireEvent()

publicclassWeldServletextendsHttpServlet{

  @Inject
  privateEvent<PostEvent>event;

  @Override
  protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{
    event.fire(newPostEvent());
  }
}

现在,发送时POST请求到servlet,所述afterPostEvent()的方法EventObserverService将被调用。

备择方案

在上一篇文章中,我通过调用setter并“手动”传递了一个新创建的实例来改进了模拟服务。 在单元测试案例中,这一切都很好,而且很好,但是我也想管理集成测试。 因此,情况如下:

  • 类路径上有两个相同接口的实现
  • 您不能更改servlet代码(例如,在服务属性中添加限定符)

考虑到CDI的确定性,您基本上应该敬酒。 实际上,没有什么比事实更遥远了。 只需使用@Alternative批注,CDI将方便地忽略已批注的类。

@Report(MAIL)@Alternative
publicclassMockMailReportServiceImplimplementsReportService{
  ...
 }

那么首先创建它有什么意义呢? 记住上面的未使用的直到beans.xml 。 因为它将接受<alternative>标记,所以它将对我们有所帮助。 这些标签激活替代方案。

<?xml version="1.0" encoding="UTF-8"?>
<beansxmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
  <alternatives>
    <class> ch.frankel.blog.weld.service.MockMailReportServiceImpl </class>
  </alternatives>
</beans>

这样,您可以拥有两个bean.xml:

  • 基本为空的标准上下文
  • 以及另一个充满替代方案的集成测试环境

平台

接缝徽标

GlassFish v3徽标

本文是使用GlassFish v3(使用Weld v1.0.1)作为平台编写的。 Weld是CDI参考实现,也是Seam框架的一部分。

总体而言,我在使用该平台时没有任何问题,但是,我无法使替代方案,拦截器和装饰器起作用。 奇怪的是,这三个都必须在WEB-INF / beans.xml中进行配置。 我不知道我做错了什么还是当前的实现中有错误。

结论

这篇分为两部分的文章仅在CDI的表面进行笔刷。 不过,恕我直言,它看起来非常有前途,我希望它能成功。

更进一步:

  • CDI概述-第1部分
  • Commons注释(JSR-250) 页面 :Commons注释具有Java中DI的注释( @Resource
  • CDI(JSR-299) 页面 :令人惊讶的是,CDI与Jav​​a EE中的DI有关
  • Weld的文档 :Weld是CDI JBoss实现,也是参考实现
  • 文章对JSR-299的优点相比,JSR-330的优点

翻译自: https://blog.frankel.ch/cdi-an-overview/2/

cdi-api

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值