Проверка, проксируется ли класс с помощью CDI 1.2

В CDI 1.2 есть способ проверить, проксифицирован ли экземпляр класса? Мне это нужно, потому что мне нужно получить имя исходного класса, а не имя прокси.

@Inject Bean bean;

public void sysout() {
    // will print something like com.Bean$$Weld9239823
    System.out.println(bean.getClass()); 

    // I don't know how to check if the bean instance if a proxy or real class instance
}

Используя классы Weld, я могу выполнить эту работу:

public void sysout() {
    // will print true because this is a proxy
    System.out.println(ProxyObject.class.isAssignableFrom(bean)); 

    // will print com.Bean
    System.out.println(((TargetInstanceProxy) bean).getTargetInstance());
}

В CDI 1.1 нет способа сделать это. Я ищу в документах CDI 1.2, был ли добавлен метод по этому поводу, но я ничего не нашел.

Итак... Я что-то упустил, а в CDI 1.2 есть способ получить исходное имя класса и экземпляр? Или, если нет, есть возможность добавить эту функцию в ближайшую функцию?


person Otávio Garcia    schedule 29.08.2014    source источник
comment
Каков вариант использования для определения класса компонента? Учитывая, что вы внедряете Bean bean, вы уже знаете, что он реализует Bean   -  person John Ament    schedule 30.08.2014
comment
Вы пробовали это решение? stackoverflow.com/a/7504552/2492784   -  person Sven    schedule 09.09.2014


Ответы (3)


Для сварки на WildFly сделайте следующее:

public boolean isProxy(Object obj) {
    try{
        return Class.forName("org.jboss.weld.bean.proxy.ProxyObject").isInstance(obj);
    } catch (Exception e) {
        log.error("Unable to check if object is proxy", e);
    }
    return false;
}

Чтобы получить фактический объект вместо прокси (мне нужно его сериализовать), я делаю это:

public Object getObject(Object obj) {
    Field f = null;
    boolean isAccessible = false;
    try {
        for(Field fi : Class.forName(handler).getDeclaredFields()) {
            if(fi.getName().equals(field)) {
                f = fi;
                isAccessible = f.isAccessible();
                f.setAccessible(true);
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    if(f == null) {
        throw new RuntimeException(new NoSuchFieldException(String.format(
                "The required field '%s' not found in '%s'. " +
                        "May be the code is obsolete for running on this application server.",
                field, method)));
    } else {
        try{
            obj = f.get(getHandler(obj));
            for(Method m : Class.forName(instance).getMethods()) {
                if(m.getName().equals(value)) {
                    return m.invoke(obj);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            f.setAccessible(isAccessible);
        }
        throw new NoSuchMethodError(String.format(
               "The required method '%s' not found in '%s'. " +
                       "May be the code is obsolete for running on this application server.",
                value, instance));
    }
}

Имейте в виду, что это самая темная магия, насколько это возможно, имеет очень низкую производительность и может сломаться при любом обновлении WildFly, если они изменят в нем классы, методы для полей.

person Anton Ermolenko    schedule 05.06.2015

Это ужасный хак, но для Weld (и, возможно, других реализаций) вы можете проверить, содержит ли имя класса «Proxy»: possibleProxy.getClass().getSimpleName().contains("Proxy"). Я использую его только для ведения журнала, чтобы получить очищенную версию обернутого имени класса:

/**
 * Get the actual simple name of the objects class that might be wrapped by
 * a proxy. A "simple" class name is not fully qualified (no package name).
 *
 * @param possibleProxy an object that might be a proxy to the actual
 * object.
 * @return the simple name of the actual object's class
 */
public static String getActualSimpleClassName(final Object possibleProxy) {
    final String outerClassName = possibleProxy.getClass().getSimpleName();
    final String innerClassName;
    if (outerClassName.contains("Proxy")) {
        innerClassName = outerClassName.substring(0, outerClassName.indexOf('$'));
    } else {
        innerClassName = outerClassName;
    }
    return innerClassName;
}
person James Marble    schedule 05.01.2015

вы можете создать метод внутри вашего прокси-компонента cdi, например

public String getClassName() {
    return this.getClass().getName();
}

это не лучшее решение, а простой прагматичный способ получить имя класса через прокси... недостатком этого метода является то, что метод должен быть в каждой реализации...

person StefanHeimberg    schedule 22.01.2015