АОП — это независимая от языка идея программирования,парадигма программирования. В бизнес-логике проекта общие модули разделены и обрабатываются горизонтально и часто используются в бизнесе, таком как ведение журнала, контроль разрешений и обработка исключений.
Быстрая навигация
- Введение АОП-зависимостей
- Общий анализ аннотаций АОП
- Реализовать разделение журнала
- Кусок псевдокода для чтения порядка выполнения
- Тест на нормальные и ненормальные условия
Парадигмы программирования в основном делятся на следующие категории:
- АОП (аспектно-ориентированное программирование) Аспектно-ориентированное программирование
- ООП (объектно-ориентированное программирование) объектно-ориентированное программирование
- POP (процедурно-ориентированное программирование)
- FP (Functional Programming) — функциональное программирование.
Внедрение зависимостей aop
Следующий пример основан наБоевая серия Spring Boot (2) Работа Jpa с хранилищем данных MySQL глава 2-1Исходный код доступен на Github
корневой каталог проектаpom.xml
добавить зависимостиspring-boot-starter-aop
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
аннотация аоп
-
@Aspect
: Аспект, который состоит из совета и точки, эта аннотация представлена как аспект в классе. -
@Joinpoint
: точка соединения, класс или метод, перехваченный АОП, вводится и используется в предварительном уведомлении.@Joinpoint
Получите имя класса, метод и параметры запроса. -
Advice
: Несколько типов уведомлений-
@Before
: предварительное уведомление, в точку@Pointcut
предварительное уведомление -
@After
: Опубликовать уведомление, в pointcut@Pointcut
Последующие уведомления либо успешны, либо ненормальны. -
@AfterReturning
: Уведомление после возврата, после того как метод выполнит возврат, возвращенные данные могут быть обработаны. -
@Around
: Surround-совет, выполняемый до и после вызова метода. -
@AfterThrowing
: выдается уведомление об исключении, метод уведомления будет выполнен, если программа выйдет из строя и возникнет исключение.
-
-
@Pointcut
: точка входа, с чего начать. Например, начиная с пакета или класса под пакетом и т. д.
Реализовать разделение журнала
содержаниеaspect
под НовыйhttpAspect.java
Класс, после получения запроса, сначала запишите соответствующую информацию журнала параметров запроса, распечатайте информацию ответа после успешного выполнения запроса и распечатайте информацию журнала ошибок для ошибки обработки запроса.
httpAspect.java
package com.angelo.aspect;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
public class HttpAspect {
// 打印日志模块
private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
// 下面会一一介绍...
Добавить точку
Определите, где находится точка входа, и инкапсулируйте общедоступный метод для повторного использования.
httpAspect.java
/**
* 定义一个公共的方法,实现服用
* 拦截UserController下面的所有方法
* 拦截UserController下面的userList方法里的任何参数(..表示拦截任何参数)写法:@Before("execution(public * com.angelo.controller.UserController.userList(..))")
*/
@Pointcut("execution(public * com.angelo.controller.UserController.*(..))")
public void log() {
}
предварительное уведомление
Часть бизнес-логики перед методом перехвата для получения некоторой информации о запросе, который используетсяGson
Обработка объекта для вывода json
httpAspect.java
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Map params = new HashMap();
params.put("url", request.getRequestURL()); // 获取请求的url
params.put("method", request.getMethod()); // 获取请求的方式
params.put("ip", request.getRemoteAddr()); // 获取请求的ip地址
params.put("className", joinPoint.getSignature().getDeclaringTypeName()); // 获取类名
params.put("classMethod", joinPoint.getSignature().getName()); // 获取类方法
params.put("args", joinPoint.getArgs()); // 请求参数
// 输出格式化后的json字符串
Gson gson = new GsonBuilder().setPrettyPrinting().create();
logger.info("REQUEST: {}", gson.toJson(params));
}
опубликовать уведомление
Кусок бизнес-логики после метода перехвата
httpAspect.java
@After("log()")
public void doAfter() {
logger.info("doAfter");
}
Объемное уведомление
Совет по окружению — это логическая операция до и после метода, которая может изменить возвращаемое значение целевого метода.org.aspectj.lang.ProceedingJoinPoint
Тип, обратите внимание, что здесь вызывается метод цели выполненияproceed()
Получите значение и верните его, иначе это вызовет исключение нулевого указателя. Возвраты ошибок также могут быть перехвачены внутри циклического уведомления.
httpAspect.java
@Around("log()")
public Object doAround(ProceedingJoinPoint point) {
try {
Object o = point.proceed();
System.out.println("方法环绕proceed,结果是 :" + o);
logger.info("doAround1");
return o;
} catch (Throwable e) {
// e.printStackTrace();
logger.info("doAround2");
return null;
}
}
Сообщите, когда вы вернетесь
В уведомлении о возврате после завершения pointcut уведомление об исключении не будет выдано в это время, если только бизнес-логика уведомления после возврата не сообщит об ошибке.
httpAspect.java
/**
* 获取响应返回值
* @param object
*/
@AfterReturning(returning = "object", pointcut = "log()")
public void doAfterReturning(Object object) {
// logger.info("RESPONSE: {}", object); 会打印出一个对象,想打印出具体内容需要在定义模型处加上toString()
logger.info("RESPONSE: {}", object.toString());
}
уведомление об исключении
Уведомление после создания исключения и уведомление после возврата в это время@AfterReturning
не будет выполняться.
httpAspect.java
@AfterThrowing(pointcut = "log()")
public void doAfterThrowing() {
logger.error("doAfterThrowing: {}", " 异常情况!");
}
Кусок псевдокода для чтения порядка выполнения
try {
// @Before 执行前通知
// 执行目标方法
// @Around 执行环绕通知 成功走finall,失败走catch
} finally {
// @After 执行后置通知
// @AfterReturning 执行返回后通知
} catch(e) {
// @AfterThrowing 抛出异常通知
}
Тест на два случая нормального и ненормального
Перед тестированиемcontroller/UserController.java
документuserList
добавлен методexception
параметр
/**
* 查询用户列表
* @return
*/
@RequestMapping(value = "/user/list/{exception}")
public List<User> userList(@PathVariable("exception") Boolean exception) {
if (exception) {
throw new Error("测试抛出异常!");
}
return userRepository.findAll();
}
- нормальный тест
curl 127.0.0.1:8080/user/list/false
Нормальное возвращаемое значение выглядит следующим образом:
- Тест на исключения
curl 127.0.0.1:8080/user/list/true
Возвращаемые значения исключения следующие:
В двух приведенных выше тестовых примерах мы видим, что объемное уведомление может выполняться как в нормальных, так и в нештатных ситуациях.
Посмотреть полный пример этой статьи на Github, глава 3-1.
Автор: Мэй Джун
Ссылка на сайт:Ууууу. ИМО OC.com/article/259…
Источник: МООК
Github: Боевая серия Spring Boot