Spring AOP Пример - Советы
Spring AOP + AspectJ
Использование AspectJ более гибкое и мощное, обратитесь к этому руководству -Using AspectJ annotation in Spring AOP.
Фреймворк Spring AOP (Aspect-oriented programming) используется для модуляции сквозных проблем в аспектах. Проще говоря, это просто перехватчик для перехвата некоторых процессов, например, когда метод выполняется, Spring AOP может перехватить исполняемый метод и добавить дополнительные функциональные возможности до или после выполнения метода.
В Spring AOP поддерживаются 4 типа советов:
-
Перед советом - беги перед выполнением метода
-
После возврата совета - Запустите после того, как метод вернет результат.
-
После выкидывания совета - Запускать после того, как метод выдает исключение
-
Вокруг совета - бегите вокруг выполнения метода, объедините все три совета выше.
В следующем примере показано, как работает совет Spring AOP.
Простой весенний пример
Создайте простой класс обслуживания клиентов с несколькими методами печати для демонстрации позже.
package com.example.customer.services; public class CustomerService { private String name; private String url; public void setName(String name) { this.name = name; } public void setUrl(String url) { this.url = url; } public void printName() { System.out.println("Customer name : " + this.name); } public void printURL() { System.out.println("Customer website : " + this.url); } public void printThrowException() { throw new IllegalArgumentException(); } }
Файл: Spring-Customer.xml - файл конфигурации бина
Запустить его
package com.example.common; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.example.customer.services.CustomerService; public class App { public static void main(String[] args) { ApplicationContext appContext = new ClassPathXmlApplicationContext( new String[] { "Spring-Customer.xml" }); CustomerService cust = (CustomerService) appContext.getBean("customerService"); System.out.println("*************************"); cust.printName(); System.out.println("*************************"); cust.printURL(); System.out.println("*************************"); try { cust.printThrowException(); } catch (Exception e) { } } }
Выход
************************* Customer name : Yong Mook Kim ************************* Customer website : http://www.example.com *************************
Простой Spring-проект для DI-компонента и вывода нескольких строк.
Spring AOP Советы
Теперь прикрепите советы Spring AOP к вышеуказанной службе поддержки клиентов.
1. Перед советом
Он будет выполнен перед выполнением метода. Создайте класс, который реализует интерфейс MethodBeforeAdvice.
package com.example.aop; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class HijackBeforeMethod implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("HijackBeforeMethod : Before method hijacked!"); } }
В файле конфигурации компонента (Spring-Customer.xml) создайте компонент для классаHijackBeforeMethod и новый прокси-объект с именем «customerServiceProxy».
-
'Target' - определите, какой бин вы хотите захватить.
-
«InterceptorNames» - укажите, какой класс (совет) вы хотите применить к этому прокси / целевому объекту.
hijackBeforeMethodBean
Note
Чтобы использовать прокси Spring, вам необходимо добавить библиотеку CGLIB2. Добавьте ниже в файл Maven pom.xml.
cglib cglib 2.2.2
Запустите его снова, теперь вы получите новый компонентcustomerServiceProxybean вместо исходного компонентаcustomerService.
package com.example.common; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.example.customer.services.CustomerService; public class App { public static void main(String[] args) { ApplicationContext appContext = new ClassPathXmlApplicationContext( new String[] { "Spring-Customer.xml" }); CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxy"); System.out.println("*************************"); cust.printName(); System.out.println("*************************"); cust.printURL(); System.out.println("*************************"); try { cust.printThrowException(); } catch (Exception e) { } } }
Выход
************************* HijackBeforeMethod : Before method hijacked! Customer name : Yong Mook Kim ************************* HijackBeforeMethod : Before method hijacked! Customer website : http://www.example.com ************************* HijackBeforeMethod : Before method hijacked!
Он будет запускать методHijackBeforeMethod’s before() перед выполнением всех методов customerService.
2. После возврата совета
Он будет выполнен после того, как метод вернет результат. Создайте класс, реализующий интерфейсAfterReturningAdvice.
package com.example.aop; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class HijackAfterMethod implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("HijackAfterMethod : After method hijacked!"); } }
Файл конфигурации бина
hijackAfterMethodBean
Запустите его снова, Выход
************************* Customer name : Yong Mook Kim HijackAfterMethod : After method hijacked! ************************* Customer website : http://www.example.com HijackAfterMethod : After method hijacked! *************************
Он будет запускать методHijackAfterMethod’s afterReturning() после каждого метода customerService, который возвращает результат.
3. После броска совета
Он будет выполнен после того, как метод сгенерирует исключение. Создайте класс, реализующий интерфейс ThrowsAdvice, и создайте методafterThrowing для перехвата исключенияIllegalArgumentException.
package com.example.aop; import org.springframework.aop.ThrowsAdvice; public class HijackThrowException implements ThrowsAdvice { public void afterThrowing(IllegalArgumentException e) throws Throwable { System.out.println("HijackThrowException : Throw exception hijacked!"); } }
Файл конфигурации бина
hijackThrowExceptionBean
Запустите это снова, вывод
************************* Customer name : Yong Mook Kim ************************* Customer website : http://www.example.com ************************* HijackThrowException : Throw exception hijacked!
Он запустит методHijackThrowException’s afterThrowing(), если методы customerService вызовут исключение.
4. Вокруг совета
Он объединяет все три приведенных выше совета и выполняется во время выполнения метода. Создайте класс, реализующий интерфейсMethodInterceptor. Вы должны вызвать“methodInvocation.proceed(); », чтобы продолжить выполнение исходного метода, иначе исходный метод не будет выполняться.
package com.example.aop; import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class HijackAroundMethod implements MethodInterceptor { @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("Method name : " + methodInvocation.getMethod().getName()); System.out.println("Method arguments : " + Arrays.toString(methodInvocation.getArguments())); // same with MethodBeforeAdvice System.out.println("HijackAroundMethod : Before method hijacked!"); try { // proceed to original method call Object result = methodInvocation.proceed(); // same with AfterReturningAdvice System.out.println("HijackAroundMethod : Before after hijacked!"); return result; } catch (IllegalArgumentException e) { // same with ThrowsAdvice System.out.println("HijackAroundMethod : Throw exception hijacked!"); throw e; } } }
Файл конфигурации бина
hijackAroundMethodBean
Запустите это снова, вывод
************************* Method name : printName Method arguments : [] HijackAroundMethod : Before method hijacked! Customer name : Yong Mook Kim HijackAroundMethod : Before after hijacked! ************************* Method name : printURL Method arguments : [] HijackAroundMethod : Before method hijacked! Customer website : http://www.example.com HijackAroundMethod : Before after hijacked! ************************* Method name : printThrowException Method arguments : [] HijackAroundMethod : Before method hijacked! HijackAroundMethod : Throw exception hijacked!
Он будет запускать методHijackAroundMethod’s invoke() после каждого выполнения метода customerService.
Заключение
Большинство разработчиков Spring просто реализуют «Советы вокруг», поскольку в них могут применяться все типы советов, но в соответствии с лучшей практикой следует выбирать наиболее подходящий тип совета для удовлетворения требований.
Pointcut
В этом примере все методы в классе обслуживания клиентов перехватываются (совет) автоматически. Но в большинстве случаев вам может потребоваться использоватьPointcut and Advisor для перехвата метода через его имя метода.
Скачать исходный код
Скачать -Spring-AOP-Advice-Examples.zip (8 КБ)