Spring Weaving: объекты @Configurable не сплетаются правильно, если они используются в качестве параметра внутри методов автопрокси.

Пожалуйста, рассмотрите следующую ситуацию с spring 4.0.7

Для Eclipselink мы используем load-time-weaver. Поэтому мы хотели поэкспериментировать с аннотацией Springs @Configurable, используя @EnableSpringConfigured с @EnableLoadTimeWeaving одновременно.

Это полностью функционально, и Spring-Beans идеально внедряются в POJO во время построения. Эта функциональность полезна для нас, потому что мы хотим сохранить некоторый код, касающийся проверки этих POJO, внутри них, а не где-то еще в Bean.

Некоторый из нашего Spring Context содержит Bean-компоненты, которые не реализуют никакого интерфейса, потому что они локальны для некоторого пакета и используются только там. Допустим, FooLogicBean — один из них. Если это должно быть внедрено в другой Bean, и некоторый Spring-AOP-Aspect (не-aspectj), например, некоторый аспект измерения производительности, находится в пути выполнения, Spring создаст автопрокси CGLIB для FooLogicBean и внедрит его. Это полностью функционально и работает отлично.

Проблемы возникают, когда мы хотим использовать POJO с аннотацией @Configurable в качестве параметра в методе FooLogicBean (например, fooLogicBean.doValidate(myPojo);), соответственно, CGLIB Proxy. В этом случае какая-то нетривиальная магия не позволяет этому POJO быть переплетенным через аспект j (AnnotationBeanConfigurerAspect из spring-aspects). Он даже никогда не вплетается в код, независимо от вызова вышеупомянутого метода doValidate().

Если мы создаем этот POJO внутри FooLogicBean, но не используем его в качестве параметра метода, он снова сплетается из-за @Configurable.

Не зная кода создания Autoproxy, мы предполагаем, что какая-то причудливая процедура маркировки препятствует обнаружению класса с помощью aspectj, если этот класс уже использовался в spring-aop. использование в данном случае означает Доступ.

Кто-нибудь экспериментировал с таким непонятным созвездием и знает решение для этого?

Заранее спасибо!


person Yusuf Iskenderoglu    schedule 16.09.2014    source источник
comment
Не могли бы вы предоставить SSCCE, пожалуйста? Может быть, проект Mavenized GitHub? Воспроизводимость всегда хороша для отладки.   -  person kriegaex    schedule 24.09.2014


Ответы (1)


Прокси создаются путем создания подклассов, т.е. когда вы создаете прокси аннотированного класса Foo:

class Foo {
  @Bar
  void bar() { }
}

прокси создается путем реализации класса

class Foo$Proxy extends Foo {
  @Override
  void bar() { 
    // Proxy logic
  }
  // Overridden methods of Object
}

Это делает класс Foo$Proxy действительной заменой Liskov для Foo. Однако применяется обычная семантика переопределения, т. е. ненаследуемые аннотации, такие как @Bar, больше не присутствуют для переопределенных методов. Как только другой API на основе аннотаций обработает ваши bean-компоненты, все аннотации исчезнут, что приведет к вашему результату. Это верно для всех видов аннотаций. Те о типах, методах и параметрах методов.

Но можно ли этого избежать? Это, безусловно, с помощью генератора прокси of">который был написан недавно и создан с учетом того, что такое аннотации, чего нельзя сказать о cglib, впервые выпущенном на заре виртуальной машины Java. Однако пока Spring не отойдет от cglib, вам придется жить с сегодняшними ограничениями.

person Rafael Winterhalter    schedule 17.09.2014
comment
Я не уверен, является ли CGLIB причиной этой проблемы. Проблема возникает не на как-то аннотированных методах, а на объектах с аннотациями, которые используются в методах прокси. Логика прокси-сервера Spring AOP совместно использует код с aspectj при обработке aop-pointcuts. Итак, я подумал, что это приводит к тому, что подсистема анализа аспектов обнаруживает/загружает классы до того, как в действие вступит часть реального аспекта пружинного контекста. Я думаю, я где-то получил информацию о том, что нужно убедиться, что аспекты-аспекты должны загружаться намного раньше, чем остальные, чтобы обнаруживать новые для плетения классы. - person Yusuf Iskenderoglu; 17.09.2014