CDI扩展动态更新属性

问题描述 投票:0回答:1

我读到CDI自定义扩展一些文件,并读取该链接类似属性装载机一些示例代码:Link-A - Link-B

我写了一个简单的CDI扩展这样的代码。

public class SystemStatisticExtension implements Extension {

    public <T> void processInjectionTarget(@Observes ProcessInjectionTarget<T> pit) {
        AnnotatedType<T> at = pit.getAnnotatedType();
        InjectionTarget<T> it = pit.getInjectionTarget();
        if (at.isAnnotationPresent(Monitor.class)) {
            pit.setInjectionTarget(new MemoryInjectionPoint<>(it, at));
        }
    }
}

这是我的InjectionPointTarget实现:

public class MemoryInjectionPoint<T> implements InjectionTarget<T> {

    private InjectionTarget<T> it;
    private AnnotatedType<T> at;
    private int kB = 1024;
    private int mB = kB / 1024;
    private int gB = mB / 1024;

    public MemoryInjectionPoint(InjectionTarget<T> it, AnnotatedType<T> at) {
        this.it = it;
        this.at = at;
    }

    @Override
    public void inject(T instance, CreationalContext<T> ctx) {
        it.inject(instance, ctx);
        int swapUsed = SystemPropertiesLoader.newInstance().getSwapUsed();
        Set<AnnotatedField<? super T>> annotatedFields = at.getFields();
        for (AnnotatedField<? super T> annotatedField : annotatedFields) {
            if (annotatedField.isAnnotationPresent(Memory.class)) {
                int memUsed = SystemPropertiesLoader.newInstance().getMemUsed();
                Memory memory = annotatedField.getAnnotation(Memory.class);
                Unit u = memory.unitType();
                switch (u) {
                    case KILOBYTE:
                        setFieldMemValue(instance, memUsed / kB, annotatedField);
                        break;
                    case MEGABYTE:
                        setFieldMemValue(instance, memUsed / mB, annotatedField);
                        break;
                    case GIGABYTE:
                        setFieldMemValue(instance, memUsed / gB, annotatedField);
                        break;
                }
            }
            if (at.isAnnotationPresent(Swap.class)) {
                Memory memory = annotatedField.getAnnotation(Memory.class);
                Unit u = memory.unitType();
                switch (u) {
                    case kILOBYTE:
                        setFieldSwapValue(instance, swapUsed / kB, annotatedField);
                        break;
                    case MEGABYTE:
                        setFieldSwapValue(instance, swapUsed / mB, annotatedField);
                        break;
                    case GIGABYTE:
                        setFieldSwapValue(instance, swapUsed / gB, annotatedField);
                        break;
                }
            }
        }
    }

    private void setFieldMemValue(T instance, int memUsed, AnnotatedField<? super T> annotatedField) {
        try {
            Field field = annotatedField.getJavaMember();
            field.setAccessible(true);
            field.setInt(instance, memUsed);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private void setFieldSwapValue(T instance, int swapUsed, AnnotatedField<? super T> annotatedField) {
        try {
            Field field = annotatedField.getJavaMember();
            field.setAccessible(true);
            field.setInt(instance, swapUsed);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postConstruct(T instance) {
        it.postConstruct(instance);
    }

    @Override
    public void preDestroy(T instance) {
        it.preDestroy(instance);
    }

    @Override
    public T produce(CreationalContext<T> ctx) {
        return it.produce(ctx);
    }

    @Override
    public void dispose(T instance) {
        it.dispose(instance);
    }

    @Override
    public Set<InjectionPoint> getInjectionPoints() {
        return it.getInjectionPoints();
    }
}

这是我的SystemPropertiesLoader:

public class SystemPropertiesLoader {
    private static Supplier<Stream<String>> supplier;

    private SystemPropertiesLoader() {

    }

    public static SystemPropertiesLoader newInstance() {
        supplier = () -> {
            Stream<String> lines = Stream.empty();
            try {
                lines = Files.lines(Paths.get("/proc/meminfo"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return lines;
        };
        return new SystemPropertiesLoader();
    }

    public int getMemTotal() {
        return Integer.valueOf(
                supplier.get()
                        .findFirst()
                        .orElse("")
                        .split(":")[1]
                        .trim()
                        .replace(" kB", ""));
    }

    public int getMemFree() {
        return Integer.valueOf(
                supplier.get()
                        .skip(1)
                        .findFirst()
                        .orElse("")
                        .split(":")[1]
                        .trim()
                        .replace(" kB", ""));
    }

    public int getSwapTotal() {
        return Integer.valueOf(supplier.get()
                .skip(14)
                .findFirst()
                .orElse("")
                .split(":")[1]
                .trim()
                .replace(" kB", ""));
    }

    public int getSwapFree() {
        return Integer.valueOf(supplier.get()
                .skip(15)
                .findFirst()
                .orElse("")
                .split(":")[1]
                .trim()
                .replace(" kB", ""));
    }

    public int getMemUsed() {
        return getMemTotal() - getMemFree();
    }

    public int getSwapUsed() {
        return getSwapTotal() - getSwapFree();
    }
} 

和注释:

@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface Memory {
    Unit unitType() default Unit.MEGABYTE;
}

@Target({METHOD,TYPE})
@Retention(RUNTIME)
public @interface Monitor {
}

而这是我使用的情况下:

@Monitor
public class MemoryMonitor {

    @Memory
    private int memUsed;

    public int getMemUsed() {
        return memUsed;
    }
}

更新的/ proc / meminfo中后,现在我的问题是memUsed属性没有改变。 怎么了 ? 可以创建动态的CDI扩展为做到这一点? 注1:我复制和粘贴整个我的代码。 注2:的/ proc / meminfo中是在支承proc文件系统Linux与Unix操作系统使用的存储器的信息。

java-ee cdi java-ee-7 java-ee-8 cdi-2.0
1个回答
0
投票

扩大评论,让我先说喷射时,每一个bean实例,只有一次。所以他们不会自动给出,以适应他们的一生中会发生变化的可能性每范围豆类通常创建一次。我能想到的两件事情:

1) Use events to notify interested parties of changes

原理很简单(在observer pattern)。我不知道如何跟踪在/ proc / meminfo中(是java.nio.file.WatchService就够了吗?)的变化,但只要你有检测到变化时,发出的事件:

public class MemInfoEvent {
    private int memUsed;
    // constructor and getter
}

当你感觉到一个变化,请拨打以下豆:

import javax.enterprise.event.Event;
...

@ApplicationScoped
public class MemInfoEventEmitter {
    @Inject
    private Event<MemInfo> memInfoEvent;

    public void handleMemInfoChange(int memUsed) {
        memInfoEvent.fire(new MemInfoEvent(memUsed));
    }
}

而看变化,只要需要:

public class BeanInterestedInMemChanges {
    public void memInfoChanged(@Observes MemInfoEvent e) {
        // do what you must
    }
}

2) Use a java.util.function.IntSupplier (or equivalent)

供应商是一个CDI豆知道如何获得memUsed,例如:

@ApplicationScoped
public class MemUsedSupplier implements IntSupplier {
    private SystemPropertiesLoader systemPropertiesLoader = ...; // could be injected, if this is more appropriate

    @Override
    public int getAsInt() {
        return systemPropertiesLoader.getMemUsed();
    }
}

注:上面的实现可能是无效的!使用为出发点 - 概念证明!低效率正在读取的/ proc / meminfo中过很多次,如果getAsInt()频繁调用。你可能想实现某种缓存/节流。

你甚至可以实现在MemoryMonitor方面SystemPropertiesLoader,再考虑潜在的低效率的服务。

© www.soinside.com 2019 - 2024. All rights reserved.