php cdi_教程:编写自己的CDI扩展

php cdi

今天,我将向您展示如何编写CDI扩展。

CDI提供了一种扩展功能的简便方法,例如

  • 添加自己的范围,
  • 启用Java核心类进行扩展,
  • 使用注释元数据进行扩充或修改,
  • 以及更多。

在本教程中,我们将实现一个扩展,该扩展将从属性文件中注入属性,就像往常一样,我将在github [更新: sources @ github ]中提供源代码 。

目标

提供扩展,使我们能够执行以下操作

@PropertyFile("myProps.txt")
public class MyProperties {@Property("version")Integer version;@Property("appname")String appname;
}

其中版本应用程序的名字在文件myProps.txt定义。

制备

首先,我们需要CDI API的依赖项

dependencies.compile "javax.enterprise:cdi-api:1.1-20130918"

现在我们可以开始了。 那么我们

弄湿

基础

每个CDI扩展的入口点都是一个实现javax.enterprise.inject.spi.Extension的类

package com.coderskitchen.propertyloader;import javax.enterprise.inject.spi.Extension;
public class PropertyLoaderExtension implements Extension {
//  More code later
}

另外,我们必须将此类的全限定名添加到META-INF / services目录中名为javax.enterprise.inject.spi.Extension的文件中。

javax.enterprise.inject.spi.Extension

com.coderskitchen.propertyloader.PropertyLoaderExtension

这些是编写CDI扩展的基本步骤。

背景资料
CDI使用Java SE的服务提供商体系结构,这就是为什么我们需要实现标记接口并将文件与实现类的FQN添加在一起的原因。

潜水更深

现在,我们必须选择正确的事件来收听。

背景资料
CDI规范定义了几个在应用程序初始化期间由容器触发的事件。
例如,在容器以bean发现开始之前,将触发BeforeBeanDiscovery

对于本教程,我们需要监听ProcessInjectionTarget事件。 对于发现的每个Java类,接口或枚举,都会触发此事件,并且可能在运行时由容器实例化该事件。
因此,让我们添加此事件的观察者:

public <T> void initializePropertyLoading(final @Observes ProcessInjectionTarget<T> pit) {
}

ProcessInjectionTarget通过getAnnotatedType方法授予对基础类的访问权限,并通过getInjectionTarget授予创建中的实例的访问权限 我们使用annotatedType获取类的注释,以检查@PropertyFile是否可用。 如果没有,我们将直接作为短路返回。

随后, InjectionTarget用于覆盖当前行为并从属性文件中设置值。

public <T> void initializePropertyLoading(final @Observes ProcessInjectionTarget<T> pit) {AnnotatedType<T> at = pit.getAnnotatedType();if(!at.isAnnotationPresent(PropertyFile.class)) {return;}}

在本教程中,我们假定属性文件直接位于类路径的根目录中。 基于此假设,我们可以添加以下代码以从文件中加载属性

PropertyFile propertyFile = at.getAnnotation(PropertyFile.class);
String filename = propertyFile.value();
InputStream propertiesStream = getClass().getResourceAsStream("/" + filename);
Properties properties = new Properties();
try {properties.load(propertiesStream);assignPropertiesToFields(at.getFields, properties); // Implementation follows
} catch (IOException e) {e.printStackTrace();
}

现在,我们可以将属性值分配给字段。 但是对于CDI,我们必须以略有不同的方式执行此操作。 我们应该使用InjectionTarget并覆盖当前的AnnotatedType。 这使CDI可以确保所有事情都可以按正确的顺序进行。

为了实现这一点,我们使用了最终的Map <Field,Object> ,我们可以在其中存储当前分配以供以后在InjectionTarget中使用 。 映射是在方法AssignPropertiesToFields中完成的。

private <T> void assignPropertiesToFields(Set<AnnotatedField<? super T>> fields, Properties properties) {for (AnnotatedField<? super T> field : fields) {if(field.isAnnotationPresent(Property.class)) {Property property = field.getAnnotation(Property.class);String value = properties.getProperty(property.value());Type baseType = field.getBaseType();fieldValues.put(memberField, value);}}

最后,我们现在将创建一个新的InjectionTarget,以将字段值分配给所有新创建的基础类实例。

final InjectionTarget<T> it = pit.getInjectionTarget();InjectionTarget<T> wrapped = new InjectionTarget<T>() {@Overridepublic void inject(T instance, CreationalContext<T> ctx) {it.inject(instance, ctx);for (Map.Entry<Field, Object> property: fieldValues.entrySet()) {try {Field key = property.getKey();key.setAccessible(true);Class<?> baseType = key.getType();String value = property.getValue().toString();if (baseType == String.class) {key.set(instance, value);}  else if (baseType == Integer.class) {key.set(instance, Integer.valueOf(value));} else {pit.addDefinitionError(new InjectionException("Type " + baseType + " of Field " + key.getName() + " not recognized yet!"));}} catch (Exception e) {pit.addDefinitionError(new InjectionException(e));}}}@Overridepublic void postConstruct(T instance) {it.postConstruct(instance);}@Overridepublic void preDestroy(T instance) {it.dispose(instance);}@Overridepublic void dispose(T instance) {it.dispose(instance);}@Overridepublic Set<InjectionPoint> getInjectionPoints() {return it.getInjectionPoints();}@Overridepublic T produce(CreationalContext<T> ctx) {return it.produce(ctx);}};pit.setInjectionTarget(wrapped);

这就是做魔术的全部。 最后,这里是ProperyLoaderExtension的完整代码。

PropertyLoaderExtension

package com.coderskitchen.propertyloader;import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.InjectionException;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.ProcessInjectionTarget;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;public class PropertyLoaderExtension implements Extension {final Map<Field, Object> fieldValues = new HashMap<Field, Object>();public <T> void initializePropertyLoading(final @Observes ProcessInjectionTarget<T> pit) {AnnotatedType<T> at = pit.getAnnotatedType();if(!at.isAnnotationPresent(PropertyyFile.class)) {return;}PropertyyFile propertyyFile = at.getAnnotation(PropertyyFile.class);String filename = propertyyFile.value();InputStream propertiesStream = getClass().getResourceAsStream("/" + filename);Properties properties = new Properties();try {properties.load(propertiesStream);assignPropertiesToFields(at.getFields(), properties);} catch (IOException e) {e.printStackTrace();}final InjectionTarget<T> it = pit.getInjectionTarget();InjectionTarget<T> wrapped = new InjectionTarget<T>() {@Overridepublic void inject(T instance, CreationalContext<T> ctx) {it.inject(instance, ctx);for (Map.Entry<Field, Object> property: fieldValues.entrySet()) {try {Field key = property.getKey();key.setAccessible(true);Class<?> baseType = key.getType();String value = property.getValue().toString();if (baseType == String.class) {key.set(instance, value);}  else if (baseType == Integer.class) {key.set(instance, Integer.valueOf(value));} else {pit.addDefinitionError(new InjectionException("Type " + baseType + " of Field " + key.getName() + " not recognized yet!"));}} catch (Exception e) {pit.addDefinitionError(new InjectionException(e));}}}@Overridepublic void postConstruct(T instance) {it.postConstruct(instance);}@Overridepublic void preDestroy(T instance) {it.dispose(instance);}@Overridepublic void dispose(T instance) {it.dispose(instance);}@Overridepublic Set<InjectionPoint> getInjectionPoints() {return it.getInjectionPoints();}@Overridepublic T produce(CreationalContext<T> ctx) {return it.produce(ctx);}};pit.setInjectionTarget(wrapped);}private <T> void assignPropertiesToFields(Set<AnnotatedField<? super T>> fields, Properties properties) {for (AnnotatedField<? super T> field : fields) {if(field.isAnnotationPresent(Propertyy.class)) {Propertyy propertyy = field.getAnnotation(Propertyy.class);Object value = properties.get(propertyy.value());Field memberField = field.getJavaMember();fieldValues.put(memberField, value);}}}
}

资料下载

完整的源代码将在git hub上提供,直到星期一晚上。 jar存档可在此处PropertyLoaderExtension中找到 。

最后的笔记

本教程说明了如何简单地向CDI框架添加新功能。 在几行代码中,添加了工作属性加载和注入机制。 在应用程序的生命周期内触发的事件提供了一种松散耦合且功能强大的方法来添加新功能,拦截bean创建或更改行为。

还可以通过引入一组生产者方法来实现属性注入,但是这种方法需要每种字段类型使用一个生产者方法。 使用这种通用方法,您只需要添加新的转换器即可启用其他类型的值的注入。

参考: 教程:在Coders Kitchen博客上,由我们的JCG合作伙伴 Peter Daum 编写您自己的CDI扩展 。

翻译自: https://www.javacodegeeks.com/2014/02/tutorial-writing-your-own-cdi-extension.html

php cdi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/344532.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【渝粤教育】广东开放大学 海外社交媒体营销 形成性考核 (45)

选择题 题目&#xff1a;经营战略计划的制定和实施&#xff0c;要以特定的()为依据。 答案&#xff1a;看左侧 题目&#xff1a;战略经营单位是企业值得为其专门制定一种经营战略的()经营单位。 答案&#xff1a;看左侧 题目&#xff1a;从20世纪初到第二次世界大战结束&#x…

centos编译mysql5.6_centos7上编译安装mysql5.6

注意&#xff0c;在做实验室统一关闭防火墙做的&#xff0c;在生产环境需要做防火墙规则的&#xff0c;大家要注意&#xff0c;做的时候尽量都是模仿生产环境的&#xff0c;比如服务一般都在/data/soft下面&#xff0c;尽量避免在/usr/local/下面。安装编译mysql所需要的软件[r…

【渝粤教育】广东开放大学 社会工作综合能力 形成性考核 (27)

选择题 题目&#xff1a;社会工作不同于其他理论性社会科学学科的重要之点是&#xff08; &#xff09;。 题目&#xff1a;关于社会工作价值观操作原则的说法&#xff0c;正确的有( )。 题目&#xff1a;作为一名专业社会工作者&#xff0c;必须遵守的原则不包括&#xff08; …

使用ELK堆栈进行日志聚合

1.简介 随着微服务的使用&#xff0c;创建稳定的分布式应用程序和摆脱许多遗留问题变得很容易。 但是微服务的使用也带来了一些挑战&#xff0c; 分布式日志管理就是其中之一。 由于微服务是隔离的&#xff0c;因此它们不共享数据库和日志文件&#xff0c;因此实时搜索&#xf…

【渝粤教育】广东开放大学 网络整合营销 形成性考核 (53)

选择题 题目&#xff1a; 网络营销应在&#xff08; &#xff09;层面做好格局方面的准备 答案&#xff1a;看左侧 题目&#xff1a; 在互联网社交时代&#xff0c;下列哪个不是其时代特征的产物。&#xff08; &#xff09; 答案&#xff1a;看左侧 题目&#xff1a; 移动端发…

mysql主从延时这么长_MySQL主从延迟问题解决

今天我们就来看看为什么会产生主从延迟以及主从延迟如何处理等相关问题。坐好了&#xff0c;准备发车&#xff01;主从常见架构随着日益增长的访问量&#xff0c;单台数据库的应接能力已经捉襟见肘。因此采用主库写数据&#xff0c;从库读数据这种将读写分离开的主从架构便随之…

【渝粤教育】广东开放大学 跨文化商务沟通 形成性考核 (42)

选择题 题目&#xff1a; The “OK” sign means in France that you think something is _________. 答案&#xff1a;看左侧 题目&#xff1a; Many words from Chinese and English are different in both the denotational meanings and connotational meanings. Which o…

python的zip方法_python zip()函数使用方法解析

这篇文章主要介绍了python zip()函数使用方法解析,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下参数iterable为可迭代的对象&#xff0c;并且可以有多个参数。该函数返回一个以元组为元素的列表&#xff0c;其…

aes256加密java_使用Java和JCEKS进行AES-256加密

aes256加密java总览 由于最近爱德华斯诺登 &#xff08; Edward Snowden&#xff09;发布了文件&#xff0c;以及针对JC Penny &#xff0c; Sony和Target等在线商业商店的黑客攻击激增&#xff0c;安全性已成为近年来讨论的重要话题。 尽管本文不会为您提供帮助防止使用非法来…

【渝粤教育】电大中专Windows操作系统作业 题库

学习好Windows10应用这门课程&#xff0c;应该&#xff08;&#xff09;。 A重视理论学习 B重视上机操作&#xff0c;多练多试 C只看不练 D可以随便学习一下 正确 正确答案&#xff1a;左边查询 学生答案&#xff1a;B 2在使用Windows时遇到困难&#xff0c;&#xff08;&#…

高可用mysql笔记_MySQL笔记-高可用方案

MySQL笔记-高可用方案一、概述MYSQL高可用方案有多种&#xff0c;本次针对其中部分方案进行实践。包括主从&#xff0c;双主&#xff0c;myqlkeepalived, mysqlmycatkeepalived。纸上得来终觉浅&#xff0c;亲自实验一下。环境信息注意两台机器时间需要保持同步&#xff0c;网络…

【渝粤教育】电大中专办公设备使用与维护 (2)_1作业 题库

1以下哪个不是现代办公硬件需求的主要依赖&#xff08;&#xff09;。 A扫描仪 B计算机 C办公桌 D打印机 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;B 2现代办公设备可分为计算机、通信&#xff08;&#xff09;三大类。 A电子工具 B办公机械 C路由器 D碎纸机 错…

无服务器冷启动不是问题-这就是为什么(对于大多数应用程序)

从无服务器开始时&#xff0c;您很快就会学习/听到有关函数冷启动的信息&#xff08;我相信无服务器云功能 API &#xff09;。 首次调用云功能时或长时间不调用后会发生冷启动。 基本上&#xff0c;服务器&#xff08;是的&#xff0c;有服务器&#xff01;&#xff09;需要一…

【渝粤教育】电大中专学前儿童健康教育作业 题库

1健康的定义是()年&#xff0c;世界卫生组织提出的。 A1945 B1948 C1955 D1958 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2健康不仅仅是没有疾病或虚弱&#xff0c;而是包括身体、心理和()方面的完好状态。 A精神 B躯体 C社会 D道德 错误 正确答案&#xff1a…

python学习与数据挖掘_Python学习之数据挖掘(三)

Pandas基础处理Pandas是什么&#xff1f;为什么用&#xff1f;核心数据结构DataFramePanelSeries基本操作运算画图文件的读取与存储高级处理4.1Pandas介绍4.1.1 Pandas介绍 - 数据处理工具panel data analysispanel面板数据 - 计量经济学 三维数据4.1.2 为什么使用Pandas便捷…

【渝粤教育】电大中专学前儿童科学教育 (14)作业 题库

1学前儿童科学教育的学习重点是() A学前儿童科学教育的内涵 B学前儿童科学教育的概念 C科学的概念 D技术的概念 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2学前儿童科学教育的学习难点是() A学前儿童科学教育的内涵 B学前儿童科学教育在儿童发展中的意义 C学前…

生成器作为(快速失败)状态机

这个想法是几周前在设计“ Generator”类时想到的&#xff0c;该类必须将输入发送给封装的Writer 。 实际上&#xff0c;它是Builder模式。 但是&#xff0c;规则有些复杂&#xff0c;用户必须以某种方式调用add...()方法&#xff0c;才能正确生成输出。 不用说&#xff0c;我…

【渝粤教育】电大中专市场营销管理20作业 题库

1.市场营销没有宏观市场营销和微观市场营销之分。该说法&#xff1a;&#xff08; &#xff09; A.错误 B.正确 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;B 2.战略选择的陷阱有&#xff1a;盲目跟随、墨守成规、军备竞赛、多方出击、孤注一掷、本末倒置。该说法…

源码包编译安装python_Python3.7源码包编译安装-Go语言中文社区

环境&#xff1a;[rootlocalhost python3]# cat /etc/redhat-releaseCentOS Linux release 7.5.1804 (Core)[rootlocalhost python3]#1、下载Python方式一&#xff1a;方式二&#xff1a;进入https://www.python.org/ftp/python/ 这里存放着所有版本的Python源码。往下拉看到最…

【渝粤教育】电大中专建筑力学 (4)作业 题库

1.下列说法不正确的是&#xff08;&#xff09;。 A.力偶在任何坐标轴上的投形恒为零 B.力可以平移到刚体内的任意一点 C.力系的合力在某一轴上的投形等于各分力在同一轴上投形的代数和 D.力使物体绕某一点转动的效应取决于力的大小和力作用线到该点的垂直距离 正确 正确答案&a…