CDI Features
一、 EL(&SpEL)
EL语言(CDI与表达式语言(EL)集成,允许在JavaServer Faces页面或JavaServer Pages页面中直接使用任何组件)
1.概述
EL是JSP内置的表达式语言,用以访问页面的上下文以及不同作用域中的对象 ,
取得对象属性的值,或执行简单的运算或判断操作。EL在得到某个数据时,会自动进行数据类型的转换。
使用EL表达式输出数据时,如果有则输出数据,如果为null则什么也不输出。
2.语法:
a.EL表达式总是放在{}中,而且前边有一个$作为前缀:${}
b.获取对象的属性值可以直接通过“对象.属性名”:${user.name};
注意:这里的属性名是get和set方法对应的属性值,并不是对象中的变量名。
c.获取对象的属性也可以通过“对象[“属性名”]”:${user["name"]}
d.获取Map中属性时可以以直接通过属性的key:${map.key},${map[key]}
e.在指定域中获取属性:
在EL表达式中如果我们直接使用属性名如:${user},它将会在四个域中由小到大依次查找。
顺序:pageScope、requestScope、sessionScope、applicationScope。
也可以指定从哪个域中获取:
${ pageScope .user }:当前页面
${requestScope.user}:当前请求
${sessionScope.user}:当前会话
${sessionScope.user}:当前应用
3.EL中包含11个隐含对象,这些对象可以在EL表达式中直接使用:
a.pageContext,和JSP中的pageContext功能一样
b.请求域:pageScope/requestScope/sessionScope/applicationScope
c.请求参数,参数对象主要用于获取get或post请求中的参数:
param:获取指定的请求参数,${param.username}
paramValues:获取请求参数数组,如:${paramValues.sport[1]}
d.其他:header/headerValues/initParam/cookie
4.EL支持数学运算和逻辑运算:
a.加减乘除:${17+5} => 22
b.取余%或mod:${17%5} => 2
c.比较运算符>,<,==,!=,<=,>=,eq,ne,lt,gt,le,ge:${3>5}或${3 gt 5} =>false
d.逻辑比较 &&或and,!或not,||或or,empty:${!true} => false
二、Decorator
装饰器与拦截器外表相似。但是,它们实际上执行的任务与拦截器执行的任务互补。拦截器执行与方法调用和bean的生命周期相关的横切任务,但不能执行任何业务逻辑。另一方面,装饰器通过拦截bean的业务方法来执行业务逻辑。这意味着它们不是可以重复使用不同类型的应用程序,而是拦截器,它们的逻辑特定于特定应用程序。
装饰器bean类还必须具有一个注释的委托注入点javax.decorator.Delegate
。此注入点可以是装饰器类的字段,构造函数参数或初始化方法参数。
可以按如下方式创建装饰器,而不是使用示例的替代TestCoderImpl
类encoder
:
@Decorator 公共抽象类CoderDecorator实现Coder { @注入 @代表 @任何 编码器编码器; public String codeString(String s,int tval){ int len = s.length(); 返回“\”“+ s +”\“变为”+“\”“+ coder.codeString(s,tval) +“\”,“+ len +”字符的长度“; } }
三、Interceptor
在CDI应用程序中使用拦截器的拦截器是用来在插方法调用或出现在相关联的目标类的生命周期事件的类。拦截器执行任务,例如日志记录或审计,这些任务与应用程序的业务逻辑分开,并且经常在应用程序中重复。这些任务通常被称为跨领域任务。拦截器允许您在一个位置指定这些任务的代码,以便于维护。当拦截器首次引入Java EE平台时,它们特定于企业bean。
拦截器类通常包含一个带注释的方法@AroundInvoke
,它指定拦截器在调用截获方法时将执行的任务。它也可以包含注释的方法@PostConstruct
,@PreDestroy
,@PrePassivate
,或者@PostActivate
,指定生命周期回调拦截器,并注明一个方法@AroundTimeout
,以指定EJB超时拦截。拦截器类可以包含多个拦截器方法,但每种类型的方法必须不超过一个。
拦截器一起,应用程序定义一个或多个拦截器绑定类型,这些类型是将拦截器与目标bean或方法相关联的注释。
例如,该billpayment
示例包含一个名为interceptor的拦截器绑定类型@Logged
和一个名为的拦截器LoggedInterceptor
。拦截器绑定类型声明看起来像限定符声明,但它注释为javax.interceptor.InterceptorBinding
:
@Inherited @InterceptorBinding @Retention(RUNTIME) @Target({METHOD, TYPE}) public @interface Logged { }
具有java.lang.annotation.Inherited
注释,以指定注释可以从超类继承。该@Inherited
注释也适用于定制范围(在本教程中没有讨论),但并不适用于预选赛。
拦截器绑定类型可以声明其他拦截器绑定。
为了在CDI应用程序中调用拦截器,它必须在beans.xml
文件中指定。例如,LoggedInterceptor
该类指定如下:
<interceptors> <class>javaeetutorial.billpayment.interceptors.LoggedInterceptor</class> </interceptors>
四、Producer(在CDI应用程序中使用生产者方法,生产者字段和处置方法)
由生产者方法产生然后可以注射的对象。通常,您在以下情况下使用生产者方法:
-
-
当你想要注入一个本身不是bean的对象时
-
当要注入的对象的具体类型可能在运行时变化
-
当对象需要一些bean构造函数不执行的自定义初始化时
-
1.使用生产者方法
生成器方法可以允许在运行时而不是在开发时或部署时选择bean实现。例如,在producermethods示例:使用Producer方法选择Bean实现中描述的示例中,托管bean定义以下生成器方法:
@Produces @Chosen @RequestScoped public Coder getCoder() { switch (coderType) { case TEST: return new TestCoderImpl(); case SHIFT: return new CoderImpl(); default: return null; } }
2.使用生产者字段生成资源
生产者字段的一个常见用途是生成一个对象,然后可以通过容器管理对象。
@Produces @UserDatabase @PersistenceContext private EntityManager em;
3.使用处置方法
可以使用生成器方法或生成器字段来生成在其工作完成时需要删除的对象。如果这样做,则需要相应的处理器方法,并使用@Disposes
注释进行注释。例如,可以按如下方式关闭实体管理器:
public void close(@Disposes @UserDatabase EntityManager em){ em.close(); }
当上下文结束时(在这种情况下,在会话结束时,因为RequestBean
具有会话范围),处理器方法被自动调用,并且close
方法中的参数接收由producer字段生成的对象。