Примеры OSGi WeavingHook

Есть ли у кого-нибудь примеры использования OSGi 4.3+ Weaving Hook Service? А как насчет AspectJ, ASM, JavaAssist? Кто-нибудь на самом деле использует OSGi WeavingHooks?

Пример в OSGi Core 5.0.0, раздел 56.2, просто не учитывает фактическое плетение и говорит, что «окончательное плетение оставляется читателю в качестве упражнения».

Моя цель:

  1. создать аннотацию (@MyAnnotation), которую я могу разместить на полях (примитивах или объектах).
  2. создайте org.osgi.framework.hooks.weaving.WeavingHook для создания классов с этой аннотацией
  3. использовать переплетение во время загрузки, чтобы указать на любую модификацию полей с этой аннотацией
  4. запускать события EventAdmin о том, что поле было изменено.
  5. динамически обновлять проводку пакета от WeavingHook для подключения к пакету EventAdmin.

У меня проблема в основном с номером 3.

В настоящее время я пытаюсь использовать AspectJ WeavingAdaptor, чтобы выполнить переплетение, но у меня возникли проблемы с подключением к нему моей библиотеки аспектов, поскольку он ожидает, что java.net.URL[] aspectURL в конструкторе будут либо jar или каталоги, которые он может найти в файловой системе, а не пакеты. Кроме того, я не уверен, как обрабатывать любые новые классы, созданные Weaver через обратные вызовы метода acceptClass(String name, bytes[]) в GeneratedClassHandler.

Может быть, WeavingAdaptor — не самое подходящее место для начала плетения? Или, может быть, мне не следует использовать AspectJ?

MyAnnotation.java

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

MyWeavingHook.java

public class MyWeavingHook implements WeavingHook {

    public class MyWeavingClassloader implements WeavingClassLoader {

        private Bundle b;

        public MyWeavingClassLoader(Bundle b) {
            this.b = b;
        }

        void acceptClass(java.lang.String name, byte[] bytes) {
            //no way to get this back into the woven classes bundle classloader?
        } 

        URL[] getAspectURLs() {
            //how do I get a handle to my aspect library that AspectJ can understand?
        }
    }

    public void weave(WovenClass myclass) {
        Bundle b = Framework.getBundle(MyWeavingHook.class);
        WeavingClassLoader wc = new WeavingClassLoader(b);
        WeavingAdaptor w = new WeavingAdaptor(wc);
        if (shouldWeave(myclass))
          myclass.setBytes(w.weave(myClass.getBytes()));
        //should catch exceptions
    }

    private boolean shouldWeave(WovenClass myclass) {
        //not sure of the best logic to pick which classes to weave yet
    }
}

MyAspect.aj

privileged aspect MyAspect {
    after() : set(* *) && @annotation(MyAnnotation) {
      //send EventAdmin event
    }
}

MyTestClass.java

public class MyTestClass {
    @MyAnnotation
    private int myField;

    public void doSomething() {
      //do stuff with myField
    }
}

Я мог бы использовать Spring AOP, но я хочу, чтобы это работало для любого пакета, а не только для bean-компонентов, созданных с помощью Spring или Blueprint. Кроме того, Equinox Weaving, похоже, еще не использует спецификацию ткацкого крючка OSGi, и я не хочу быть привязанным к Equinox. У меня нет проблем с отказом от AspectJ, если что-то другое работает лучше.

Ссылка на аналогичный вопрос: Можно ли сделать байт-код манипуляции при использовании OSGi?

ОБНОВИТЬ:

Конечным результатом является то, что я просто использовал Equinox Aspects и установил его в Karaf. Было 3 бандла, одна библиотека и системное свойство. Я буду использовать его до тех пор, пока они либо не обновят его до OSGi weaving, либо я не напишу свои собственные OSGi weaving hooks, чтобы использовать код AspectJ, аналогичный Equinox Aspects. Мне не нравятся индикаторы переплетения, необходимые для работы Equinox Aspects, потому что они вводят пакет require-bundle/reexport или import-package в AspectJ RT в связке, которую нужно сплести. Эта зависимость должна быть динамически добавлена ​​и рекомендована вне пакета.


person John Ellinwood    schedule 21.03.2013    source источник
comment
Для ткацких крючков OSGi вы получаете byte[] класса, который вам нужно изменить. Вы не должны пытаться загрузить измененный byte[]. Это будет сделано фреймворком OSGi после того, как будут вызваны все ткацкие крючки.   -  person BJ Hargrave    schedule 21.03.2013
comment
@BJHargrave да, так говорит спецификация. Вопрос в том, какие фреймворки или библиотеки совместимы с OSGi и легко вставляются в метод WeavingHook.weave(), с помощью которого я могу модифицировать исходный класс byte[]... и есть ли примеры того, как кто-то действительно это делает?   -  person John Ellinwood    schedule 21.03.2013
comment
На ум приходят ASM или BCEL.   -  person BJ Hargrave    schedule 22.03.2013
comment
@BJHargrave хорошо, оба они были перечислены в моем вопросе (косвенно bcel через aspectj). Подумав об этом, я думаю, что мне нужна мощь аспекта, но, просматривая исходный код аспекта, он просто не подходит для osgi. Единственная полезная структура, которую я вижу, - это аспекты равноденствия. Изменение этого для использования ткацких крючков OSGi вместо расширений равноденствия кажется менее трудоемким, чем написание моего собственного адаптера вокруг аспекта.   -  person John Ellinwood    schedule 25.03.2013


Ответы (2)


Взгляните на ProxyWeavingHook из модуля прокси Apache Aries. Он использует библиотеку ASM напрямую для изменения байт-кода на более низком уровне.

person Chetan    schedule 08.04.2013
comment
Ваш единственный ответ, и это разумный ответ. Конечным результатом является то, что я просто использовал Equinox Aspects и установил его в Karaf. Было 3 бандла, одна библиотека и системное свойство. Я буду использовать его до тех пор, пока они либо не обновят его до OSGi weaving, либо я не напишу свои собственные OSGi weaving hooks, чтобы использовать код AspectJ, аналогичный Equinox Aspects. Мне не нравятся индикаторы переплетения, необходимые для работы Equinox Aspects, потому что они вводят пакет require-bundle/reexport или import-package в AspectJ RT в связке, которую нужно сплести. Эта зависимость должна быть динамически добавлена ​​и рекомендована вне пакета. - person John Ellinwood; 11.05.2013

WeavingAdaptor ожидает, что ваш WeavingClassLoader будет производным от URLClassLoader, поэтому оба доступных конструктора в конечном итоге делают одно и то же. Посетите http://www.slideshare.net/mfrancis/bytecode-weaving, чтобы узнать, как BundleWiring можно использовать для получения доступа к URL-адресам путей к классам. Вы можете добавить пакеты среды выполнения AspectJ в wovenClass.getDynamic'Imports(), чтобы избежать прямых ссылок на AspectJ. BundleWiring — это также способ предоставить URL-адреса AspectJ для WeavingAdaptor.

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

person Tuomas Kiviaho    schedule 24.05.2013