这是一个CDI便携式扩展,它从属性文件中读取值并配置Java EE组件的字段。在Java EE 6中,这适用于任何支持注入的Java EE组件,包括servlets、EJBs、托管bean、拦截器等。
在此示例中,例如org.mydomain.blog.Blogger的属性位于名为org/mydomain/blog/Blogger.properties的资源中,并且属性的名称必须与要配置的字段的名称匹配。因此Blogger.properties将包含
firstName=Gavin lastName=King
该便携式扩展通过包装容器InjectionTarget并从inject()方法中设置字段值。
public class ConfigExtension implements Extension {
<X> void processInjectionTarget(ProcessInjectionTarget<X> pit) {
final InjectionTarget<X> it = pit.getInjectionTarget();
final Map<Field, Object> configuredValues = new HashMap<Field, Object>();
AnnotatedType<X> at = pit.getAnnotatedType();
String propsFileName = at.getClass().getSimpleName() + ".properties";
InputStream stream = at.getJavaClass().getResourceAsStream(propsFileName);
if (stream!=null) {
try {
Properties props = new Properties();
props.load(stream);
for (Map.Entry<Object, Object> property : props.entrySet()) {
String fieldName = property.getKey().toString();
Object value = property.getValue();
try {
Field field = at.getJavaClass().getField(fieldName);
field.setAccessible(true);
if ( field.getType().isAssignableFrom( value.getClass() ) ) {
configuredValues.put(field, value);
}
else {
//TODO: do type conversion automatically
pit.addDefinitionError( new InjectionException("field is not of type String: " + field ) );
}
}
catch (NoSuchFieldException nsfe) {
pit.addDefinitionError(nsfe);
}
}
}
catch (IOException ioe) {
pit.addDefinitionError(ioe);
}
finally {
stream.close();
}
}
InjectionTarget<X> wrapped = new InjectionTarget<X>() {
@Override
public void inject(X instance, CreationalContext<X> ctx) {
it.inject(instance, ctx);
for (Map.Entry<Field, Object> configuredValue: configuredValues.entrySet()) {
try {
configuredValue.getKey().set(instance, configuredValue.getValue());
}
catch (Exception e) {
throw new InjectionException(e);
}
}
}
@Override
public void postConstruct(X instance) {
it.postConstruct(instance);
}
@Override
public void preDestroy(X instance) {
it.dispose(instance);
}
@Override
public void dispose(X instance) {
it.dispose(instance);
}
@Override
public Set<InjectionPoint> getInjectionPoints() {
return it.getInjectionPoints();
}
@Override
public X produce(CreationalContext<X> ctx) {
return it.produce(ctx);
}
};
pit.setInjectionTarget(wrapped);
}
}
该便携式扩展必须部署在一个包含名为META-INF/services/javax.enterprise.inject.spi.Extension的jar文件中,该文件包含完全限定的扩展类名称。