Spring AOP - Wdrożenia

Wiosna wspiera @AspectJ annotation style podejście i schema-based podejście do wdrażania niestandardowych aspektów.

Oparte na schemacie XML

Aspekty są implementowane przy użyciu zwykłych klas wraz z konfiguracją opartą na XML.

Aby użyć tagów przestrzeni nazw AOP opisanych w tej sekcji, musisz zaimportować schemat sprężynowego AOP, opisany w następujący sposób -

<?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>

Deklarowanie aspektu

Na aspect jest deklarowana przy użyciu <aop:aspect> element, a do fasoli zapasowej odwołuje się przy użyciu ref atrybut w następujący sposób.

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

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

Tutaj "aBean" zostanie skonfigurowany i wstawiony zależność tak, jak każdy inny bean Spring, jak widzieliśmy w poprzednich rozdziałach.

Deklarowanie PointCut

ZA PointCutpomaga w określaniu punktów złączenia (tj. metod), które mają być wykonane, z różnymi radami. Podczas pracy z konfiguracją opartą na schemacie XML PointCut zostanie zdefiniowany w następujący sposób -

<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>

Poniższy przykład definiuje PointCut o nazwie „businessService”, który będzie pasował do metody getName () dostępnej w klasie Student w pakiecie 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>

Deklarowanie porad

Możesz zadeklarować dowolną z pięciu porad wewnątrz <aop: aspekt> za pomocą elementu <aop: {NAZWA PORADY}> w następujący sposób.

<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>

Możesz użyć tego samego doRequiredTasklub różne metody dla różnych porad. Metody te zostaną zdefiniowane jako część modułu aspektów.

Oparty na @AspectJ

@AspectJ odnosi się do stylu deklarowania aspektów jako zwykłych klas Java z adnotacjami Java 5. Obsługa @AspectJ jest włączana przez dołączenie następującego elementu do pliku konfiguracyjnego opartego na schemacie XML.

<aop:aspectj-autoproxy/>

Deklarowanie aspektu

Klasy aspektu są jak każdy inny normalny bean i mogą mieć metody i pola tak jak każda inna klasa, z tym wyjątkiem, że zostaną opatrzone adnotacją @Aspect w następujący sposób.

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {

}

Zostaną skonfigurowane w XML, jak każdy inny bean w następujący sposób.

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

Deklarowanie PointCut

ZA PointCutpomaga w określaniu punktów złączenia (tj. metod), które mają być wykonane, z różnymi radami. Podczas pracy z konfiguracją opartą na @AspectJ deklaracja PointCut składa się z dwóch części -

  • Wyrażenie PointCut, które dokładnie określa, które wykonania metod nas interesują.

  • Podpis PointCut zawierający nazwę i dowolną liczbę parametrów. Rzeczywista treść metody jest nieistotna i w rzeczywistości powinna być pusta.

Poniższy przykład definiuje PointCut o nazwie „businessService”, który będzie zgodny z wykonaniem każdej metody dostępnej w klasach w pakiecie com.xyz.myapp.service.

import org.aspectj.lang.annotation.PointCut;

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

Poniższy przykład definiuje PointCut o nazwie „getname”, który będzie pasował do metody getName () dostępnej w klasie Student w pakiecie com.tutorialspoint.

import org.aspectj.lang.annotation.PointCut;

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

Deklarowanie porad

Możesz zadeklarować dowolną z pięciu porad, używając adnotacji @ {ADVICE-NAME}, jak podano poniżej. Zakłada się, że zdefiniowano już metodę podpisu BusinessService () PointCut.

@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(){
   ...
}

Możesz zdefiniować PointCut inline dla dowolnej porady. Poniżej znajduje się przykład definiowania inline PointCut przed poradą.

@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
   ...
}