Сохранять аннотации на прокси CGLIB?
Я пытаюсь создать объект, используя структуру AOP, которая использует CGLIB для создания прокси-объектов.
Как ни странно, "расширенный" прокси-объект лишен ЛЮБЫХ аннотаций предыдущего класса!
Может ли кто-нибудь сказать мне, как я могу заставить CGLIB сохранить аннотации на прокси-серверах, которые он создает?
Ура!
Nirav
Ответы
Ответ 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, и это довольно расширяемо. Надеюсь, вы хорошо пользуетесь библиотекой.