Поняття
Модель зрізів зі Spring дозволяє повторно використовувати зрізи незалежно від типів порад. Можна орієнтувати різні типи порад за допомогою того самого зрізу.
Інтерфейс org.springframework.aop.Pointcut
є центральним інтерфейсом, який використовується для
орієнтування порад на певні класи та методи. Нижче наведено повний інтерфейс:
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
Поділ інтерфейсу Pointcut
на дві частини дозволяє повторно використовувати частини зіставних класів і
методів, а також робити тонкі операції компонування (наприклад, виконувати "об'єднання" з іншим засобом зіставлення
методів (method matcher)).
Інтерфейс ClassFilter
використовується для обмеження зрізу встановленим набором цільових класів. Якщо
метод matches()
завжди повертає true, то збігаються всі цільові класи. У наступному лістингу показано
визначення інтерфейсу ClassFilter
:
public interface ClassFilter {
boolean matches(Class clazz);
}
Інтерфейс MethodMatcher
зазвичай важливіший. Нижче наведено повний інтерфейс:
public interface MethodMatcher {
boolean matches(Method m, Class<?> targetClass);
boolean isRuntime();
boolean matches(Method m, Class<?> targetClass, Object... args);
}
Метод matches(Method, Class)
використовується для того, щоб перевірити, чи цей зріз відповідає цьому
методу в цільовому класі. Це обчислення може бути виконане під час створення проксі АОП, щоб уникнути необхідності
проведення перевірки кожного виклику методу. Якщо метод matches
з двома аргументами повертає
true
для цього методу, а метод isRuntime()
повертає true
для MethodMatcher,
то метод відповідності з трьома аргументами буде викликаний за кожного виклику методу. Це дозволяє зрізу переглядати
аргументи, що передалися до виклику методу безпосередньо перед початком цільової поради.
Більшість реалізацій MethodMatcher
є статичними, що означає, що їх метод isRuntime()
повертає false
. У цьому випадку метод matches
з трьома аргументами ніколи не викликається.
Операції над зрізами
Spring підтримує операції (зокрема, об'єднання та перетин) над зрізами.
Об'єднання означає методи, які збігаються з будь-яким зі зрізів. Перетин означає методи, які збігаються з обома
зрізами. Об'єднання зазвичай більш практична операція. Ти можеш компонувати зрізи за допомогою статичних методів
класу org.springframework.aop.support.Pointcuts
або за допомогою класу ComposablePointcut
з того самого пакета. Однак, використання виразів зрізів з AspectJ зазвичай є більш простим підходом.
Зрізи виразів AspectJ
Починаючи з версії 2.0, найбільш важливим типом зрізу, що використовується Spring, є org.springframework.aop.aspectj.AspectJExpressionPointcut
.
Це зріз, який використовує бібліотеку, що постачається AspectJ, для синтаксичного аналізу рядка виразу зрізу з
AspectJ.
Обговорення підтримуваних зрізів-примітивів з AspectJ див. у попередньому розділі.
Зручні реалізації зрізів
Spring надає кілька зручних реалізацій зрізів. Деякі з них можна використовувати безпосередньо; інші призначені для побудови підкласів у специфічних для застосування зрізах.
Статичні зрізи
Статичні зрізи засновані на методі та цільовому класі і не можуть враховувати аргументи методу. Для більшості випадків використання достатньо статичних зрізів — і вони найкращі. Spring може обчислити статичний зріз лише один раз, якщо метод викликається вперше. Після цього немає потреби повторно обчислювати зріз при кожному виклику методу.
В решті цього розділу описані деякі реалізації статичних зрізів, які включені до Spring.
Зрізи регулярних виразів
Одним із очевидних способів зазначення статичних зрізів є регулярні вирази. Декілька АОП-фреймворків, крім Spring,
дозволяють здійснювати це. org.springframework.aop.support.JdkRegexpMethodPointcut
— це загальний зріз
регулярного виразу, який використовує підтримку регулярних виразів у JDK.
За допомогою класу JdkRegexpMethodPointcut
можна вказати список рядків шаблонів. Якщо будь-який з них
збігається, то зріз набуде значення true
. (Як наслідок, результуючий зріз фактично буде об'єднанням
вказаних шаблонів).
У цьому прикладі показано, як використовувати:
<bean id="settersAndAbsquatulatePointcut"
class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
Spring надає зручний клас RegexpMethodPointcutAdvisor
, який дозволяє також посилатися на
Advice
(пам'ятай, що Advice
може бути порадою "перехоплення", порадою " перед", порадою
"генерація виключення" та іншими). За лаштунками Spring використовує JdkRegexpMethodPointcut
.
Використання RegexpMethodPointcutAdvisor
спрощує зв'язування, оскільки один боб інкапсулює і зріз, і
пораду, як показано в наступному прикладі:
<bean id="settersAndAbsquatulateAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="beanNameOfAopAllianceInterceptor"/>
</property>
<property name="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
Ти можеш використовувати RegexpMethodPointcutAdvisor
з будь-яким типом Advice
.
Зрізи, керовані атрибутами
Важливим типом статичного зрізу є зріз, керований метаданими. При цьому використовуються значення атрибутів метаданих (зазвичай метаданих на рівні джерела).
Динамічні зрізи
Обчислення динамічних зрізів є більш ресурсомістким завданням. Ці зрізи враховують аргументи методу, і навіть статичну інформацію. Це означає, що їх обчислення необхідно проводити при кожному виклику методу і що результат не можна кешувати, оскільки аргументи змінюватимуться.
Основним прикладом є зріз control flow
.
Зрізи потоку керування
Зрізи потоку керування (control flow pointcuts) зі Spring концептуально схожі на зрізи cflow
з AspectJ,
хоча й не такі ефективні. (Наразі немає способу, що дозволяє встановити, щоб зріз проходив нижче точки з'єднання, що
збігається з іншим зрізом.) Зріз потоку керування збігається з поточним стеком викликів. Наприклад, він може
спрацювати, якщо точка з'єднання викликана методом з пакета com.mycompany.web
або класом SomeCaller
.
Зрізи потоку керування встановлюються за допомогою org.springframework.aop.support.ControlFlowPointcut
.
Суперкласи зрізів
Spring надає практичні суперкласи (батьківські класи) зрізів, які можуть допомогти реалізувати ваші власні зрізи.
class TestStaticPointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method m, Class targetClass) {
// повертає true, якщо спеціально вказані критерії збігаються
}
}
class TestStaticPointcut : StaticMethodMatcherPointcut() {
override fun matches(method: Method, targetClass: Class<*>): Boolean {
// повертає true, якщо спеціально вказані критерії збігаються
}
}
Існують також суперкласи для динамічних зрізів. Ти можеш використовувати спеціальні зрізи з будь-яким типом порад.
Спеціальні зрізи
Оскільки зрізи в Spring AOP є класами Java, а не функціями мови (як в AspectJ), ти можеш оголошувати спеціальні зрізи, як статичні, так і динамічні. Спеціальні зрізи у Spring можуть бути довільно складними. Проте, якщо це можливо, рекомендується використовувати мову виразів зрізів AspectJ.