AspectJ и Spring LTW не работают при апскейтинге - PullRequest
2 голосов
/ 24 февраля 2012

Я установил LTW с AspectJ и весной довольно быстро и успешно. Вот установка: beans.xml:

<context:annotation-config />
<aop:aspectj-autoproxy />
<context:spring-configured />
<context:load-time-weaver />
<context:component-scan base-package="com.test.service" />

Мой сервис, который будет автоматически подключен к классу:

@Service
public class MyService {
}

Родительский класс:

public class Bar {
}

Настраиваемый класс, который автоматически связывает сервис и расширяет Bar.

@Configurable
public class BarExtended extends Bar{
    @Autowired
    private MyService service;
    public MyService getWeavedInObject(){
        return service;
    }
}

И просто класс, который имеет ссылку на родительский класс Bar:

public class Foo {
    private Bar bar;
    public void setBar(Bar bar) {
        this.bar = bar;
    }
}

И успешный контрольный пример. Он просто создает экземпляр BarExtended и проверяет, работает ли LTW. Класс Foo ничего не делает.

@Test
public void simple(){
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

Этот тест выполняется зеленым. НО следующие тестовые неудачи:

@Test
public void simple(){
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    foo.setBar(barExtended);
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

Я просто вставляю строку, в которой класс BarExtended установлен в Foo. Из-за уныния AspjectJ не работает.

Кстати, когда я изменяю класс Foo, чтобы использовать класс BarExtended (поэтому нет необходимости в обновлении):

public class Foo {
    private BarExtended bar;
    public void setBar(BarExtended bar) {
        this.bar = bar;
    }
}

Приведенный выше тест будет работать. У кого-нибудь есть идея, почему AspjectJ ведет себя так странно, когда настраиваемый объект выгружается?

Редактировать: Follwing также не работает:

@Test
public void simple() {
    Foo foo = new Foo();
    BarExtended barExtended = new BarExtended();
    Bar bar = (Bar) new BarExtended();
    foo.setBar(bar);
    assertNotNull("LTW didn't work.", barExtended.getWeavedInObject());
}

Для другого объекта BarExtended установлено значение Foo, а первый объект barExtended игнорируется AspectJ. НО используя отражение для создания экземпляров BarExtended работ:

@Test
public void simple() throws InstantiationException, IllegalAccessException{
    Foo foo = new Foo();
    Bar barExtended = (Bar) BarExtended.class.newInstance();
    foo.setBar(barExtended);
    assertNotNull("LTW didn't work.", ((BarExtended)barExtended).getWeavedInObject());
}

Странно, не правда ли?

Большое спасибо

С уважением,

Andreas

Ответы [ 2 ]

1 голос
/ 16 января 2014

У меня такая же проблема в настройке JUnit со стандартной настройкой пружинного инструмента. При запуске того же кода в контейнере WebSphere с WebSphereLoadTimeWeaver никаких проблем не возникает!

Мой код openJPA увеличивает время сборки. Мой @Configurable и некоторые другие аспекты выполняются во время загрузки.

Мое лучшее предположение состоит в том, что усовершенствование стратегии наследования openjpa позже вступает в конфликт с LTW и, следовательно, дает мне некоторые проблемы с нулевым указателем в сочетании с @ Configuarable.

Пример JUNIT

AbstactWhatEver x = new Concrete (); // @Configurable работает

AbstactWhatEver x = new Concrete (); x.callAnyMethod (); // выдает проблему LTW по аннотации openjpa, следовательно, @Configurable не работает

ОБЪЯВЛЕНИЯ ПРИМЕРЫ РАБОТЫ В WEBSPHERE ENV.

Вы когда-нибудь решали эту проблему?

1 голос
/ 02 июля 2012

У меня были проблемы в прошлом, когда я думал, что LTW был настроен, но не по причинам, в которых я не совсем уверен. Так что теперь я на 100% явный в моей конфигурации внесите следующие изменения в ваш конфигурационный файл и посмотрите, все ли работает.

  <context:load-time-weaver aspectj-weaving="on" />

удалите <aop:aspectj-autoproxy /> из вашей конфигурации, она вам не нужна, у вас действительно работает LTW.

Когда вы запускаете тестирование JUnit, передаете ли вы аргумент vm, чтобы сообщить JUnit, где находится агент LTW? Если нет, то у вас не работает LTW.

Вот что говорят о документах <context:load-time-weaver />

Активирует Spring LoadTimeWeaver для этого контекста приложения, доступный в виде компонента с именем "LoadTimeWeaver". Любой компонент, реализующий интерфейс LoadTimeWeaverAware, получит Ссылка LoadTimeWeaver автоматически; например, поддержка начальной загрузки JPA в Spring. Ткач по умолчанию определяется автоматически. Начиная с версии 2.5: обнаружение Sun GlassFish, Oracle OC4J, агента виртуальной машины Spring и любой ClassLoader, поддерживаемый Spring's ReflectiveLoadTimeWeaver (например, TomcatInstrumentableClassLoader). Активация AspectJ время загрузки определяется через простой флаг (атрибут aspectj-weaving), с преобразователем класса AspectJ, зарегистрированным через Spring LoadTimeWeaver. Плетение AspectJ будет активировано по умолчанию, если присутствует ресурс "META-INF / aop.xml" в пути к классам. Это также активирует текущий контекст приложения для применения внедрения зависимости к неуправляемые классы, которые создаются вне фабрики bean-компонентов Spring (как правило, аннотированные классы с аннотацией @Configurable). Это произойдет, только если AnnotationBeanConfigurerAspect находится на classpath (то есть spring-aspect.jar), эффективно активирующий «сконфигурированный пружиной» по умолчанию. Смотрите Javadoc для org.springframework.context.annotation.EnableLoadTimeWeaving для получения информации о коде на основе альтернативы начальной загрузке ткацкой поддержки.

Таким образом, в заключение можно сказать, что на самом деле <context:load-time-weaver /> действительно относится к определению bean-компонента с идентификатором loadTimeWeaver и сканированию пути к классу в поисках специальных файлов, таких как aop.xml, чтобы определить, нужно ли включать aspectJ. Чтобы убедиться, что aspectJ включен, вам действительно нужно установить aspectj-weaving="on" таким образом, если он не может включить aspectJ по какой-либо причине, он не будет работать при запуске, что именно то, что вы хотите. В моем веб-приложении у меня есть тест, который я запускаю при запуске веб-приложения, чтобы убедиться, что аспектJ работает, и если это не так, он жалуется.

...