OSGi WeavingHook Примеры
У кого-нибудь есть примеры использования OSGi 4.3+ Weaving Hook Service? А как насчет AspectJ, ASM, JavaAssist? Кто-нибудь на самом деле использует OSGi WeavingHooks?
Пример в разделе 56.2 OSGi Core 5.0.0 просто опускает фактическое плетение и говорит, что "финальное плетение оставлено читателю в качестве упражнения".
Моя цель состоит в том, чтобы:
- создайте аннотацию (@MyAnnotation), которую я могу разместить на полях (примитивах или объектах).
- создайте org.osgi.framework.hooks.weaving.WeavingHook для создания классов с этой аннотацией
- использовать время загрузки для точечной резки при любой модификации полей с этой аннотацией
- инициировать события EventAdmin, чтобы поле было изменено.
- динамически обновлять проводку пакета от WeavingHook для подключения к пакету EventAdmin.
Моя проблема в основном с № 3.
В настоящее время я пытаюсь использовать AspectJ WeavingAdaptor для выполнения ткачества, но у меня возникают проблемы с подключением к нему моей библиотеки аспектов, так как ожидается, что java.net.URL[] aspectURLs в конструкторе будет либо jar, либо каталогами он может найти в файловой системе, а не в связках. Кроме того, я не уверен, как обрабатывать какие-либо новые классы, сгенерированные ткачом посредством обратных вызовов к методу 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 Aspect и установил его в Karaf. Было 3 комплекта, одна библиотека и системное свойство. Я буду использовать его до тех пор, пока они не обновят его для нас, ткачество OSGi, или я напишу свои собственные хуки для ткачества OSGi, чтобы использовать код AspectJ, аналогичный аспектам Equinox. Мне не нравятся ткацкие индикаторы, необходимые для работы Аспектов Equinox, потому что они вводят require-bundle/reexport или import-package на AspectJ RT в пакете, который нужно сплести. Эта зависимость должна быть динамически добавлена и рекомендована вне пакета.
2 ответа
Взгляните на ProxyWeavingHook от прокси-модуля Apache Aries. Он использует библиотеку ASM напрямую для изменения байт-кода, так что более низкий уровень.
WeavingAdaptor ожидает, что ваш WeavingClassLoader будет получен из URLClassLoader, поэтому оба доступных конструктора в основном делают одно и то же. Посетите страницу http://www.slideshare.net/mfrancis/bytecode-weaving чтобы узнать, как можно использовать BundleWiring для получения доступа к URL-адресам классов. Вы можете добавить исполняемые пакеты AspectJ в wovenClass.getDynamic'Imports(), чтобы избежать прямых ссылок на AspectJ. BundleWiring - это также способ предоставления URL-адресов AspectJ для WeavingAdaptor.
Я думаю, что нет никакого способа поддержать новые классы, поступающие из acceptClass, потому что ткацкий хук заявляет, что динамический импорт может использоваться только внутри метода weave.