Load Time Weaving для классов, не входящих в мой проект

Я пытаюсь использовать Spring, чтобы обеспечить переплетение времени загрузки для нескольких классов в проекте, который я создал. У меня возникают проблемы с его работой, когда я вызываю класс, который не входит в мой локальный проект.

Я создал класс с именем ExampleClass, и когда я выполняю @Around для метода в нем, я вижу изменения, которые я сделал для возврата, однако, когда я пытаюсь сделать то же самое для String, я не могу получить какие-либо результаты.

Это мой код Aspect:

@Pointcut("call(* java.lang.String.*(..))")
public void cutString() {}

@Before("cutString()")
public void aroundString() throws Throwable {
    System.out.println("I Never See This");
}

Вот мой вызов этого кода:

public class Main {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("classpath:my-context.xml");

        String string = new String("I Only See This");
        System.out.println(string.toLowerCase());
    }
}

Содержимое my-context.xml — это просто <context:load-time-weaver />.

У меня определен aop.xml, который, как я уже сказал, работает для одного класса, но не для другого:

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver>
        <include within="com.example.*" />
        <include within="java.lang.String" />
    </weaver>

    <aspects>
        <aspect name="com.example.PerformMonitor" />
    </aspects>
</aspectj>

Я что-то упустил, или это ограничение Spring и AspectJ?


person Nicholas    schedule 10.04.2013    source источник


Ответы (2)


По умолчанию аспект не будет плести какие-либо стандартные классы Java. Насколько я помню, это ограничение для предотвращения утечек безопасности. Это описано в документации aspectj. Вероятно, есть свойство, которое позволяет изменить это поведение, но вы должны быть очень уверены, что вам это нужно, прежде чем начать это делать.

Просто создайте еще одну банку с одним своим классом и попробуйте сплести эту. Это должно работать из коробки.

person Martin Frey    schedule 10.04.2013

Мартин Фрей прав. Есть способы сплести классы JDK (я так делал), но это немного сложно и не для новичков — да и в основном не нужно. Ваша альтернатива - перехватывать вызовы, а не выполнение ваших внешних методов. Таким образом, вам не нужно вплетаться в них. Чисто и легко. Просто используйте call() вместо execution() для внешних классов.

person kriegaex    schedule 10.04.2013
comment
Так что, если я вырезал свою точку как @Pointcut("call(* java.lang.String.*(..))"), это должно позволить мне перехватывать вызовы методов на String? Я пробую это, и это все еще не соответствует моей точке зрения. - person Nicholas; 10.04.2013
comment
Да, так и должно быть — при условии, что вы контролируете вызываемый объект и можете вплетать в него код. Вы не можете перехватывать вызовы методов String из сторонних библиотек, если только вы также не вплетаете в них свои аспекты посредством вплетения во время загрузки или бинарного вплетения, создавая новые версии и переупаковывая их в JAR-файлы, заменяя исходные. У вас есть много вариантов. - person kriegaex; 10.04.2013
comment
Я настроил этот pointcut, и я контролирую вызов string.toLowerCase(), и я вызываю свой pointcut из @Before, и я не вижу, чтобы мой System.out.println() распечатывал то, что я хочу. - person Nicholas; 10.04.2013
comment
Тогда, вероятно, ваша конфигурация LTW или ваша конфигурация Spring неверны. [Обновление:] Предупреждение: убедитесь, что вы действительно используете полный AspectJ, а не только Spring AOP, который работает только для Spring bean-компонентов!!! - person kriegaex; 10.04.2013
comment
Мой выше AOP.xml - это то, что я установил, это выглядит правильно? - person Nicholas; 10.04.2013
comment
К сожалению, сегодня вечером у меня нет компьютера, я просто отвечаю со своего iPad. Я не очень часто использую LTW, в следующий раз, когда я буду в офисе, нужно проверить его в своей IDE. - person kriegaex; 10.04.2013
comment
Спасибо за помощь. Я буду продолжать копать, но и дам комментарий, если получу его, но любая помощь будет оценена. - person Nicholas; 10.04.2013
comment
Я заработал, не имея new ClassPathXmlApplicationContext("classpath:my-context.xml");. - person Nicholas; 11.04.2013
comment
Я все еще в пути. Ну, чтобы использовать AspectJ, вам не нужен Spring. Spring имеет собственное расширение в стиле АОП. Вероятно, ваша конфигурация каким-то образом пыталась использовать этот. - person kriegaex; 11.04.2013