Подтвердить что ты не робот

Сохранять аннотации на прокси CGLIB?

Я пытаюсь создать объект, используя структуру AOP, которая использует CGLIB для создания прокси-объектов. Как ни странно, "расширенный" прокси-объект лишен ЛЮБЫХ аннотаций предыдущего класса!

Может ли кто-нибудь сказать мне, как я могу заставить CGLIB сохранить аннотации на прокси-серверах, которые он создает?

Ура! Nirav

4b9b3361

Ответ 1

CGLIB создает подклассы заданных классов для создания прокси. Аннотации не сохраняются в подклассах, если они явно не указаны в определении аннотации. @Inherited аннотация используется для этой цели.

Вы можете использовать эту аннотацию в аннотациях, которые вы определяете, и сделать их доступными в подклассах следующим образом:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
}

Ответ 2

Это не проблема с "сохранением" аннотаций. Прокси CGLIB являются фактически генерируемыми подклассами класса целевого объекта. Эти подклассы могут не иметь аннотаций, но их суперкласс (т.е. Ваш собственный класс) будет по-прежнему иметь их. Любой используемый вами аннотационный код должен иметь возможность посмотреть иерархию классов для поиска аннотаций.

Ответ 3

Это действительная проблема (теперь я запускаюсь сам): а) не все фреймворки достаточно умны, чтобы проверять родительские классы; б) даже если они достаточно умны, они могут не делать этого. Последнее, похоже, имеет место с Гисом. FWIW, https://issues.apache.org/jira/browse/WICKET-1130 - проблема, над которой я работал, когда я это нашел.

Ответ 4

Cglib не способен сохранять аннотации, не меняя своей внутренней реализации. Это, однако, довольно сложно и поверьте мне, что я попробовал. Моя измененная версия, которую я, наконец, придумала, была настолько сложной, что я решил скорее реализовать Byte Buddy, другую библиотеку генерации кода, которая способна к такой функциональности.

Вот пример того, как вы можете создать подкласс, который

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation { }

@MyAnnotation
class MyClass { }

assertThat(new ByteBuddy()
  .subclass(Object.class)
  .attribute(TypeAttributeAppender.ForSuperType.INSTANCE)
  .make()
  .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
  .getLoaded()
  .isAnnotationPresent(MyAnnotation.class), is(true));

Byte Buddy поставляется с обширной полнотекстовой документацией и javadoc, и это довольно расширяемо. Надеюсь, вы хорошо пользуетесь библиотекой.