аннотации метода null при прокси через CGLIB - PullRequest
8 голосов
/ 23 января 2012

Я испытываю странное поведение при поиске аннотаций для метода, принадлежащего классу, проксированному через CGLIB. Мы используем CGLIB в Spring, и если я аннотирую метод только с аннотацией, он работает хорошо (я могу получить аннотации с помощью метода getAnnotations() для соответствующего объекта Method). Если вместо этого я аннотирую метод двумя аннотациями (независимо от порядка аннотаций), getAnnotations() просто вернет null. Обе аннотации имеют RetentionPolicy.RUNTIME.

Я читал, что есть некоторые проблемы с CGLIB, но странно, что он просто работает для одной аннотации и возвращает ноль, когда я ставлю 2 аннотации.

Есть предложения?

(с использованием Spring 3.0.5 и CGLIB 2.2.2)

Добавление кода:

1-я аннотация:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Produces {
    ResultType[] value();
}

2-я аннотация

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JamonMonitored {
    String type() default "";
    String tag() default "";
}

А блок кода для проверки аннотаций

Collection<Method> candidates = Collections2.filter(Arrays.asList(executorInstance.getClass().getMethods()), new Predicate<Method>() {
    @Override
    public boolean apply(Method input) {
        return input.getAnnotation(Produces.class) != null;
    }
});

if (candidates.isEmpty()) {
    // throws exception
}

Если я аннотирую метод с помощью @Produces и @JamonMonitored, getAnnotation(Produces.class) всегда равен null.

Ответы [ 2 ]

17 голосов
/ 25 января 2012

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

Spring должен сам выполнять большую обработку аннотаций, чтобы ориентироваться в своем пути.вокруг прокси, суперклассов, интерфейсов и тд.Логика для этого инкапсулирована и представлена ​​в классе org.springframework.core.annotation.AnnotationUtils.В вашем случае это звучит так, как будто вы хотите использовать findAnnotation служебный метод , то есть

@Override
public boolean apply(Method input) {
    return AnnotationUtils.findAnnotation(input, Produces.class) != null;
}
1 голос
/ 18 января 2013

Другой вариант - указать @Inherited в определении аннотации.Это заставит аннотацию появляться даже в подклассе, сгенерированном cglib.Конечно, в некоторых сценариях вы бы не хотели, чтобы ваша аннотация появлялась в «реальных» подклассах, так что это может быть не вариант для каждого сценария, и нужно использовать помощники Spring, как показано в skaffman

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...