最近、技術省は突然、コード上のプロジェクトチームによって、風のレビューコードを吹き、原則として、これは良いことであるべきで、他の人が自分のコードの欠点を指摘し、ギャップをチェックし、自分のコーディング能力を向上させるために、ギャップを埋めることができます大きな助けを持って、結局のところ、コードの自分のレビューは非常に簡単です "自分の文章に酔って"。
しかし、コードレビューの詳細なレベルはとんでもない、行ごとに分析し、単にトレーニングコースああです。それは私の村だけ4おじいちゃんの郡キー小学校教育を持っている場合は、666〜、開発を開始することができることが保証され、月に耳を傾けるために来て、言っても過言ではありません!
コードの方向を最適化するために選択し、メソッドの入力と戻り結果のログは、負担、各メソッドは、これらの2つのログを持つことになり、冗長なコードの大きな山、どのような印刷形式は、非常に乱雑です。
public OrderDTO getOrder(OrderVO orderVO, String name) {
log.info("注文詳細入力パラメータ:orderVO={},name={}", JSON.toJSONString(orderVO), name);
OrderDTO orderInfo = orderService.getOrderInfo(orderVO);
log.info("注文の詳細結果: orderInfo={}", JSON.toJSONString(orderInfo));
return orderInfo;
}
AOPの次の使用は、ビジネスコードの量を削減しながら、パラメータに要求メソッドを達成するために、ログの統一された印刷の戻り結果は、ログの印刷形式の混乱を避けるために。
カスタム・アノテーション
@Target({ElementType.METHOD})
カスタム切り出しアノテーション @PrintlnLog はログを出力するために使用され、アノテーションのパーミッションはメソッドのみに使用を制限し、アノテーションにはカスタムメソッドからの出力ログを記述するために使用されるパラメータ記述が1つだけあります。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface PrintlnLog {
/**
* カスタムログの説明メッセージテキスト
*
* @return
*/
String description() default "";
}
クラスの切り取り
次に、@PrintlnLog アノテーションの対応するカットオーバー実装を記述します。 doBefore() は、メソッドのカスタム記述、入力パラメータ、リクエストメソッド、リクエスト URL、および呼び出されたメソッドの場所を出力し、doAround() はメソッドの返り結果を出力します。
注:カットオーバーが実行される環境を指定したい場合は、@Profileアノテーションを使用すると、特定の環境でのみログを出力できます。
@Slf4j
@Aspect
@Component
//@Profile({"dev"}) //特定の環境でのみログを出力する
public class LogAspect {
private static final String LINE_SEPARATOR = System.lineSeparator();
/**
* カスタム @PrintlnLog ファセットエントリとしてのアノテーション
*/
@Pointcut("@annotation(com.chengxy.unifiedlog.config.PrintlnLog)")
public void PrintlnLog() {
}
/**
* @param joinPoint
*
* @description メソッド入力ログの印刷をカットする
*
*/
@Before("PrintlnLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String methodDetailDescription = this.getAspectMethodLogDescJP(joinPoint);
log.info("------------------------------- start --------------------------");
/**
* カスタム・メソッドの説明を出力する
*/
log.info("Method detail Description: {}", methodDetailDescription);
/**
* リクエスト入力を印刷する
*/
log.info("Request Args: {}", JSON.toJSONString(joinPoint.getArgs()));
/**
* リクエスト・メソッドを印刷する
*/
log.info("Request method: {}", request.getMethod());
/**
* 打印请求 url
*/
log.info("Request URL: {}", request.getRequestURL().toString());
/**
* 呼び出されたメソッドのフルパスとその実行メソッドを出力する
*/
log.info("Request Class and Method: {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
}
/**
* @param proceedingJoinPoint
*
* @description ファセットメソッドの結果ログを出力する
*
*/
@Around("PrintlnLog()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
String aspectMethodLogDescPJ = getAspectMethodLogDescPJ(proceedingJoinPoint);
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
/**
* 結果を出力する
*/
log.info("{},Response result : {}", aspectMethodLogDescPJ, JSON.toJSONString(result));
/**
* メソッドの実行時間
*/
log.info("Time Consuming: {} ms", System.currentTimeMillis() - startTime);
return result;
}
/**
*
* @description カットオーバー・メソッドの実行後に
*
*/
@After("PrintlnLog()")
public void doAfter(JoinPoint joinPoint) throws Throwable {
log.info("------------------------------- End --------------------------" + LINE_SEPARATOR);
}
/**
* @param joinPoint
*
* @description @PrintlnLog アノテーションされたファセットメソッドの詳細情報
*
*/
public String getAspectMethodLogDescJP(JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
return getAspectMethodLogDesc(targetName, methodName, arguments);
}
/**
* @param proceedingJoinPoint
*
* @description @PrintlnLog アノテーションされたファセットメソッドの詳細情報
*
*/
public String getAspectMethodLogDescPJ(ProceedingJoinPoint proceedingJoinPoint) throws Exception {
String targetName = proceedingJoinPoint.getTarget().getClass().getName();
String methodName = proceedingJoinPoint.getSignature().getName();
Object[] arguments = proceedingJoinPoint.getArgs();
return getAspectMethodLogDesc(targetName, methodName, arguments);
}
/**
* @param targetName
* @param methodName
* @param arguments
*
* @description カスタムアノテーションのパラメータ
*
*/
public String getAspectMethodLogDesc(String targetName, String methodName, Object[] arguments) throws Exception {
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
StringBuilder description = new StringBuilder("");
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description.append(method.getAnnotation(PrintlnLog.class).description());
break;
}
}
}
return description.toString();
}
}
アプリケーション
入ってくる参照を表示して結果ログを返す必要があるメソッドに @PrintlnLog アノテーションを追加し、カスタム・メソッドの説明を追加します。
@RestController
@RequestMapping
public class OrderController {
@Autowired
private OrderService orderService;
@PrintlnLog(description = "OrderDetailsController")
@RequestMapping("/order")
public OrderDTO getOrder(OrderVO orderVO, String name) {
OrderDTO orderInfo = orderService.getOrderInfo(orderVO);
return orderInfo;
}
}