日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

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

發布時間:2023/12/3 php 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

總結

以上是生活随笔為你收集整理的php cdi_教程:编写自己的CDI扩展的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。