Spring Advanced (AOP アプリケーション) - AOP を動的にプロキシした後のコントローラー層のプライベート メソッドへの無効なアクセスの問題

ここに画像の説明を挿入します

序文

動的プロキシと AOP (Aspect Oriented Programming) は Spring の重要かつ難しいポイントであり、深く理解し、プロジェクトに柔軟に適用する方法を学ぶ必要があります。

このブログでは、動的プロキシ AOP の実際のアプリケーションで遭遇するプライベート メソッドのアクセス失敗の問題を紹介します。

その他の関連する拡張メソッド AOP の記事のリストは次のとおりです。

Spring の基本 (コア コンテナ) - 設定ファイルからアノテーション開発 & オブジェクト作成 + メンバー変数割り当て IOC & 拡張メソッド AOP まで

ここに画像の説明を挿入します
Spring Advanced (AOP の理解) - 静的/動的プロキシ & アスペクト指向プログラミング AOP (アスペクト指向プログラミング) & ロギング & 拡張メソッド

ここに画像の説明を挿入します

導き出す


動的プロキシ AOP 後のコントローラー層での無効なプライベート メソッド アクセスの問題の発見と解決

1. 拡張メソッド AOP を使用してコントローラー層を拡張します

ここに画像の説明を挿入します

package com.tianju.fresh.aop;

import com.woniu.fresh.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
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 javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;

/**
 * 进行日志的记录
 */
@Component
@Aspect
@Slf4j // 用lombok.extern.slf4j.Slf4j;
public class LoggingAsp {
    
    

    // 给所有标注了@Controller注解的方法做增强
    @Before("@within(org.springframework.web.bind.annotation.RestController)")

    public void log(JoinPoint joinPoint){
    
    
        String className = joinPoint.getTarget().getClass().getSimpleName(); // 获取类名
        String methodName = joinPoint.getSignature().getName(); // 获取方法名
        Object[] args = joinPoint.getArgs(); // 获取传的参数

        // 获取一下httpRequest
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        String username;
        try {
    
    
            // 获得用户名
            String jwt = request.getHeader("jwt");
            Map userInfo = JwtUtil.getUserInfo(jwt);
            log.debug("登陆的用户的信息:"+userInfo);
            username = userInfo.get("username")+"-"+userInfo.get("realName");
        } catch (Exception e) {
    
    
            username = "神秘的用户";
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        Date date = new Date();
        String formattedDate = sdf.format(date);

        // ip地址
        String ipAddress = request.getRemoteAddr();
        log.info(">>>> LOG {} 从ip地址 {} {}访问了 {} 类的 {} 方法,传的参数为 {} ",
                formattedDate, ipAddress, username,className,methodName, Arrays.toString(args));
    }
}

2. コントローラーの API を呼び出すときに、依存関係の注入が null であることが判明しました。

拡張メソッド AOP をオンにすると、エラー メッセージに null ポインター例外が表示されます。これは奇妙です。@autowired が普及していないためです。これは、このクラスが IOC コンテナーに存在することを示していますが、実際には null であると言われています。

ここに画像の説明を挿入します

3. デバッグモードで表示を開始します

API インターフェイスを表示およびアクセスするには、デバッグ モードを使用します。依存関係が挿入された 2 つのエンティティ クラスが null であることが判明したため、エラー (null ポインター例外) が報告されます。

ここに画像の説明を挿入します

4. 理由: コントローラー層のメソッドはプライベートです

調べたところ、コントローラー層のメソッドがプライベートであることが判明し、この問題であることが判明しました。

ここに画像の説明を挿入します

5. 解決策: 公開に変更する

これを public に変更すると、これら 2 つは null ではなくなります。

ここに画像の説明を挿入します

要約する

動的プロキシ AOP 後のコントローラー層での無効なプライベート メソッド アクセスの問題の発見と解決

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/Pireley/article/details/133341988