Учебники

Spring AOP — Внедрения

Spring поддерживает подход стиля аннотации @AspectJ и подход на основе схемы для реализации пользовательских аспектов.

XML на основе схемы

Аспекты реализуются с использованием обычных классов наряду с конфигурацией на основе XML.

Чтобы использовать теги пространства имен AOP, описанные в этом разделе, вам необходимо импортировать схему весеннего AOP, описанную следующим образом:

<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:aop = "http://www.springframework.org/schema/aop"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
   http://www.springframework.org/schema/aop 
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

   <!-- bean definition & AOP specific configuration -->

</beans>

Объявление аспекта

Аспект объявляется с использованием элемента <aop: aspect> , а на компонент поддержки ссылаются с помощью атрибута ref следующим образом.

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

Здесь «aBean» будет настроен, и зависимость будет внедрена, как и любой другой bean-компонент Spring, как вы видели в предыдущих главах.

Объявление PointCut

PointCut помогает в определении точек соединения (т. Е. Методов ), представляющих интерес для выполнения с различными советами. При работе с конфигурацией на основе XML-схемы PointCut будет определяться следующим образом:

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">

   <aop:PointCut id = "businessService"
      expression = "execution(* com.xyz.myapp.service.*.*(..))"/>
      ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

В следующем примере определяется PointCut с именем «businessService», который будет соответствовать выполнению метода getName (), доступного в классе Student в пакете com.tutorialspoint.

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">

   <aop:PointCut id = "businessService"
      expression = "execution(* com.tutorialspoint.Student.getName(..))"/>
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

Объявление Советов

Вы можете объявить любой из пяти советов внутри <aop: aspect>, используя элемент <aop: {ADVICE NAME}> следующим образом.

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">
      <aop:PointCut id = "businessService"
         expression = "execution(* com.xyz.myapp.service.*.*(..))"/>

      <!-- a before advice definition -->
      <aop:before PointCut-ref = "businessService" 
         method = "doRequiredTask"/>

      <!-- an after advice definition -->
      <aop:after PointCut-ref = "businessService" 
         method = "doRequiredTask"/>

      <!-- an after-returning advice definition -->
      <!--The doRequiredTask method must have parameter named retVal -->
      <aop:after-returning PointCut-ref = "businessService"
         returning = "retVal"
         method = "doRequiredTask"/>

      <!-- an after-throwing advice definition -->
      <!--The doRequiredTask method must have parameter named ex -->
      <aop:after-throwing PointCut-ref = "businessService"
        throwing = "ex"
         method = "doRequiredTask"/>

      <!-- an around advice definition -->
      <aop:around PointCut-ref = "businessService" 
         method = "doRequiredTask"/>
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

Вы можете использовать один и тот же doRequiredTask или разные методы для разных советов. Эти методы будут определены как часть аспектного модуля.

На основе @AspectJ

@AspectJ относится к стилю объявления аспектов как обычных классов Java, аннотированных аннотациями Java 5. @AspectJ относится к стилю объявления аспектов как обычных классов Java, аннотированных аннотациями Java 5. Поддержка @AspectJ включается включением следующего элемента в файл конфигурации на основе XML-схемы.

<aop:aspectj-autoproxy/>

Объявление аспекта

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

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {

}

Они будут настроены в XML как любой другой компонент следующим образом.

<bean id = "myAspect" class = "org.xyz.AspectModule">
   <!-- configure properties of aspect here as normal -->
</bean>

Объявление PointCut

PointCut помогает в определении точек соединения (т. Е. Методов ), представляющих интерес для выполнения с различными советами. При работе с конфигурацией на основе @AspectJ объявление PointCut состоит из двух частей:

  • Выражение PointCut, которое точно определяет, какие методы выполнения нас интересуют.

  • Подпись PointCut, содержащая имя и любое количество параметров. Фактическое тело метода не имеет значения и фактически должно быть пустым.

Выражение PointCut, которое точно определяет, какие методы выполнения нас интересуют.

Подпись PointCut, содержащая имя и любое количество параметров. Фактическое тело метода не имеет значения и фактически должно быть пустым.

В следующем примере определяется PointCut с именем «businessService», который будет соответствовать выполнению каждого метода, доступного в классах в пакете com.xyz.myapp.service.

import org.aspectj.lang.annotation.PointCut;

@PointCut("execution(* com.xyz.myapp.service.*.*(..))") // expression 
private void businessService() {}  // signature

В следующем примере определяется PointCut с именем ‘getname’, который будет соответствовать выполнению метода getName (), доступного в классе Student в пакете com.tutorialspoint.

import org.aspectj.lang.annotation.PointCut;

@PointCut("execution(* com.tutorialspoint.Student.getName(..))") 
private void getname() {}

Объявление Советов

Вы можете объявить любой из пяти советов, используя аннотации @ {ADVICE-NAME}, как указано ниже. Это предполагает, что вы уже определили метод подписи PointCut businessService ().

@Before("businessService()")
public void doBeforeTask(){
   ...
}

@After("businessService()")
public void doAfterTask(){
   ...
}

@AfterReturning(PointCut = "businessService()", returning = "retVal")
public void doAfterReturnningTask(Object retVal){
   // you can intercept retVal here.
   ...
}

@AfterThrowing(PointCut = "businessService()", throwing = "ex")
public void doAfterThrowingTask(Exception ex){
   // you can intercept thrown exception here.
   ...
}

@Around("businessService()")
public void doAroundTask(){
   ...
}

Вы можете определить PointCut inline для любого из советов. Ниже приведен пример определения встроенного PointCut для перед рекомендацией.