2013-06-27 3 views
2

Мне нужно ввести несколько методов для каждого инициализированного объекта с помощью AspectJ.AspectJ pointcut on объект-конструктор

Я думал, что с помощью этого:

pointcut vistaInjection(Object o) 
    : initialization(java.lang.Object.new()) 
    && target(o) 
    && !within(objectAspect); 

before(Object o): methodInjection(o){System.err.println("INIT");} 

к Pointcut инициализации объекта, так что я могу привнести эти методы непосредственно в объект, который является частью любого другого объекта.

Однако он не работает. Вы знаете, почему? Или что может быть другим способом, как сделать 100% уверенным, что каждый отдельный инициализированный объект будет pointcut? * .new не работает для таких вещей, как String, Lists и другие.

Спасибо!

+0

Есть ошибки? Не могли бы вы более подробно рассказать о функции mal? – JEY

+0

нет нет ошибок. просто создание объекта не вызывает советы .. Извините, я не понимаю, что такое функция «mal»? Я только что понял, что создание других объектов не инициализирует конструктор Object, потому что это было бы бесполезно в любом случае. Мне нужно будет найти другой способ, как указывать все создания объектов. – Marosh

ответ

15

Пользователь selig прав: Вы, вероятно, не хотите перехватывать все создания объектов, особенно не в классах JDK/JRE. Но для чего это стоит, вот объяснение того, что работает и как и что нет:

небольшое приложение драйвера:

public class Application { 
    public static void main(String[] args) { 
     new Application(); 
     new String(); 
    } 
} 

Аспект с различными типами конструктора связанных срезов в/совет:

public aspect ObjectCreationAspect { 
    before() : preinitialization(*.new(..)) && !within(ObjectCreationAspect) { 
     System.out.println(thisJoinPointStaticPart); 
    } 

    before() : initialization(*.new(..)) && !within(ObjectCreationAspect) { 
     System.out.println(thisJoinPointStaticPart); 
    } 

    before() : call(*.new(..)) && !within(ObjectCreationAspect) { 
     System.out.println(thisJoinPointStaticPart); 
    } 

    before() : execution(*.new(..)) && !within(ObjectCreationAspect) { 
     System.out.println(thisJoinPointStaticPart); 
    } 
} 

выход тканого приложения водителя:

call(Application()) 
preinitialization(Application()) 
initialization(Application()) 
execution(Application()) 
call(java.lang.String()) 

Объяснение:

Существуют различные виды ткачества в AspectJ:

  • Compile времени соткать (CTW): Только классы, которые составитель AJC (AspectJ компилятор) можно соткать. Это исключает классы JDK/JRE, а также сторонние библиотеки, которые вы не компилируете из источника. выход образца сверху показывает эффект ткачества во время компиляции.
  • Бинарное ткачество (BW): Компилятор AspectJ используется для компиляции кода аспекта непосредственно в существующий байт-код. Это работает с вашими предварительно скомпилированными классами приложений, а также с сторонними библиотеками. Теоретически он также работает с классами JDK/JRE, если вы положили rt.jar на путь компилятора AspectJ. Плетение JDK/JRE немного сложно, но я сделал это раньше. Вы можете создать новую тканую версию rt.jar или просто небольшой JAR-файл с несколькими сплетенными JDK-классами, которые затем приступают к загрузке класса JDK/JRE при запуске приложения.
  • Нагрузочное время (LTW): В основном это BW, но выполняется динамически во время загрузки класса. В этом сценарии AspectJ вы можете переплести только классы, которые загружаются загрузчиком классов под воздействием искателя. Таким образом, он работает с вашим собственным кодом и сторонними библиотеками, но обычно не с классами начальной загрузки JDK/JRE, которые загружаются до загрузки загрузчика. Это проблема типа «курица и яйцо»: ткач нуждается в JRE для запуска, прежде чем он может быть загружен, но для того, чтобы сплести классы JRE, ткач должен был быть там до того, как эти классы будут загружены.

Теперь то, что вы легко можете сделать, это перехват вызовов к JDK/JRE конструкторам из вашего собственного кода Одера тканого третий кода партии, как вы можете видеть на выход журнала линии, говоря call(java.lang.String()). Однако вы не можете перехватывать внутренние вызовы из класса JRE классу JRE.

Сказав все, что я действительно задаюсь вопросом, какую ужасную вещь вы хотите сделать. Я имею в виду, вы объясняете это, и это звучит как потрясающая ошибка дизайна. Или вы хотите заново изобрести колесо и написать какой-то профилировщик или отладчик, который уже существует. Что вы ожидаете от перехвата создания каждого объекта? Это значительно замедлит ваше приложение, резко увеличит потребление памяти и создаст еще больше объектов, если только строки, которые вы регистрируете. Пожалуйста, передумайте и попытайтесь подумать о том, что вы действительно хотите сделать. Возможно, тогда мы можем предложить разумный способ достижения вашей цели.

+0

Большое спасибо за ваш сложный ответ. Я работаю над экспериментом, абсолютно не на реальном приложении ... Я хочу реализовать измененную версию возможностей объекта. Это означает, что я могу создать объект и деавторизовать определенные методы и передать этот объект третьей стороне. Если третья сторона пытается выполнить метод де-авторизации, генерируется исключение. Это должно применяться ко всем объектам, даже JDK/JRE. Я достигаю этого путем статической модификации, объявляя родителей .... всем классам. Опять же, даже классы Java. – Marosh

+0

Затем пользователь может вызвать e. o.deauthorize ("methodName") и в o.methodName, исключение вызывается. Есть два варианта, которые я рассмотрел. Во-первых, чтобы создать точки в runtime, что я нашел как невозможно, во-вторых, деавторизация с помощью Annotations (пока еще не полностью изучена), а третья - простая грубая сила, выполняемая перехватом всех вызовов методов в приложении и сравнивая их с " деавторизованные методы ". Последнее глупо и делает все это необоснованным, потому что это замедлит работу системы, как вы сказали, чрезвычайно. – Marosh

0

Вы пробовали

pointcut vistaInjection(Object o) 
    : (initialization(*.new()) || (initialization(*.new(..))) 
    && target(o) 
    && !within(objectAspect); 

т.е. вызова .new() ни на что и позволяет не некоторые аргументы.

Примечание - вы, вероятно, не хотите поднимать все создания объектов .. что вы планируете делать с ними!

+0

Нет, это не работает. Я пытаюсь реализовать что-то похожее на возможности объекта с помощью AOP. Таким образом, каждому объекту вводится код, который позволяет отменить доступ к определенному методу. Затем, когда выполняется этот неавторизованный метод, генерируется исключение. В концепции я предлагаю, чтобы каждый объект находился в одном и том же объекте. поэтому мне нужно выбрать каждое создание объекта. – Marosh