スプリングとスプリングガイドのコアコンセプト


Springの目標


簡単なテストと遅い欠陥を提供します!

Spring三角形



IoC / DI

  • IoC(Inversion Of Control)
    Springでは、通常、開発者が管理するのではなく、新しいJavaオブジェクトが作成され、Spring Containerに渡されます.すなわち,開発者からフレームワークに移行すると,制御の対象管理権限が付与され,「制御の逆転」と呼ばれる.
  • DI:依存注入
    依存性を分離し、コードテストを容易にします.
    DIでは、不可能な場合はMockなどの技術で安定したテストができます.
    コードを拡張または変更すると、影響は最小限に抑えられます(抽象的)
    循環参照をブロックできます.
  • DI例


    main class
    import java.io.UnsupportedEncodingException;
    
    public class Main {
        public static void main(String[] args) throws UnsupportedEncodingException {
            String url = "https://velog.io/write?id=8489d4eb-e663-4bb7-b05d-9b12494d99c5";
    
            // base64 encoder를 사용할 때
            Encoder encoder = new Encoder(new Base64Encoder());
            // URL encoder를 사용할 때
            //Encoder encoder = new Encoder(new URLEncoder());
            String result = encoder.encode(url);
            System.out.println(result);
        }
    }
    
    次にメインコードを見てみましょう.指定したURLを符号化する必要があります.この場合、Base 64エンコーダとURLエンコーダの2つの選択肢があります.2つのエンコーダを状況に応じて柔軟に修正する必要がある場合、上記のようにしてパラメータをエンコーダの成長に伝達することができる.これがDIです.
    ->すなわち,DIは最上位層の作成者や関数のパラメータに必要なオブジェクトを注入することで,最下位層で発生したコード修正を排除し,コードの再利用性を高めることができる.

    SpringのIoC Containerの例


    プライマリコード
    package com.example.ioc_study_with_spring;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ApplicationContext;
    
    @SpringBootApplication
    public class IoCStudyWithSpringApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(IoCStudyWithSpringApplication.class, args);
    
            ApplicationContext context = ApplicationContextProvider.getContext();
    
    
            Encoder encoder = context.getBean(Encoder.class);
    
            String url = "https://velog.io/write?id=8489d4eb-e663-4bb7-b05d-9b12494d99c5";
    
            String result = encoder.encode(url);
            System.out.println(result);
        }
    
    }
    
    以下にSpringでIoC Contenterを実装するマスターコードを示す.ここで見たいのがApplicationContextです.このApplicationContextは、Springに登録されている空という名前のオブジェクトを管理するオブジェクトです.つまり、IOCContenerと言えるでしょう.
    ここでは、Encodeというオブジェクトがbeanとして登録され、getBeanがインポートされているのを見ることができます.ただし、Base 64とURLエンコーダをインポートする必要がありますが、どちらをインポートするかは不明です.そのため、Encoderクラスをチェックする必要があります.
    Encoderオブジェクト
    package com.example.ioc_study_with_spring;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class Encoder{
        private IEncoder iEncoder;
    
        public Encoder(IEncoder iEncoder){
            this.iEncoder = iEncoder;
        }
    
        public void setIEncoder(IEncoder iEncoder){
            this.iEncoder = iEncoder;
        }
    
        public String encode(String message){
            return iEncoder.encode(message);
        }
    }
    
    ここでは@コンポーネント宣言を確認できます.コンポーネント宣言は、このオブジェクトをIOC containerに登録する空です.しかし、ここではどのエンコーダを使用するかは確定できません.IoC containerはIEncoder beanオブジェクトを自動的に指定するためです.したがって、IEncoderインプリメンテーションオブジェクトを表示する必要があります.
    package com.example.ioc_study_with_spring;
    
    import org.springframework.context.annotation.Primary;
    import org.springframework.stereotype.Component;
    
    import java.util.Base64;
    
    @Component
    public class Base64Encoder implements IEncoder {
        @Override
        public String encode(String message) {
            return Base64.getEncoder().encodeToString(message.getBytes());
    
        }
    }
    
    次はBase 64 Encoderオブジェクトです.@Component言語が使われているのも見えます.したがって、IoCコンテナに登録されているIEcoder空がBase 64であり、Encoderオブジェクトに自動的に登録されているオブジェクトがBase 64であると判断できます.しかし、URLエンコーダもあります.beanとして登録します.2つのIEncoderオブジェクトが登録されているため、IoC Containerは混乱します.したがって、エラーコードを発行します.このソリューションもSpringによって提供されます.
    URLコード
    package com.example.ioc_study_with_spring;
    
    import org.springframework.context.annotation.Primary;
    import org.springframework.stereotype.Component;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    
    @Primary
    @Component
    public class UrlEncoder implements IEncoder {
    
        @Override
        public String encode(String message) {
            try {
                return URLEncoder.encode(message,"UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    
    URL Encoderを見ると@Primaryという名前があります.次に、複数のbeanが登録されると、最初に一致するbeanについて説明する.したがって、プログラムを実行すると、まずURLエンコーダに注入されます.

    観点に向けたAOP計画


  • ほとんどの場合、スプリングアプリケーションはMVCで階層設計を使用する.主に3つの層を使用します.アプリケーション層、ビジネス層、Infra層です.

  • ≪アプリケーション・レイヤ|Application Layer|emdw≫:クライアント中心の論理を適用し、クライアントと通信するレイヤ.

  • ビジネス層:内部ポリシーに基づいてLogicを開発します.

  • Infra Layer:データベースと外部へのバインドを処理します.
  • 関心を持つ

    =>AOPは、複数の階層で共通の使用を実現する部分である場合に、コード重複を防止するために使用する方法である.
    キーテクノロジ
    Annotationでは,@Asspect Javaで広く使用されているAOPフレームワークを説明し,@Pointcut機能をAOPを定義するクラスに適用するように設定する前に,@Afterメソッドの実行に成功した.呼び出しが成功したときにAfterReturingメソッドの実行を制御する失敗例と具体的な値@AroundBeforAfter

    AOP使用例1


    ParameterAOPコード
    package com.example.demo.Aop;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    @Aspect
    @Component
    public class ParameterAop {
        @Pointcut("execution(* com.example.demo.Controller..*.*(..))")
        private void cut(){
    
        }
    
        @Before("cut()")
        public void before(JoinPoint joinPoint){
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            Method method = methodSignature.getMethod();
            System.out.println(method.getName());
            Object[] args = joinPoint.getArgs();
            for(Object obj : args){
                System.out.println("type : " + obj.getClass().getSimpleName());
                System.out.println("value : " + obj);
            }
        }
    
        @AfterReturning(value = "cut()", returning = "obj")
        public void afterReturn(JoinPoint joinPoint, Object obj){
            System.out.println("return obj : " + obj);
        }
    }
    
    次のコードを見ると、@AsspectarNovationで始まります.@クエリ宣言は、クラスがAOPに属するクラスであることを示します.@Pointcut言語テストは、aopクラスがどの範囲で活動するかを制限します.この部分は数式がたくさんあって難しいので、次回検索します.
    AOPクラスは、@Before@AfterReturn操作によりメソッド実行前後に実行できます.

    AOP使用例2


    TimerAOPコード
    package com.example.demo.Aop;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StopWatch;
    
    @Aspect
    @Component
    public class TimerAop {
        @Pointcut("execution(* com.example.demo.Controller..*.*(..))")
        private void cut(){}
    
        @Pointcut("@annotation(com.example.demo.Annotation.Timer)")
        private void enableTimer(){}
    
        @Around("cut() && enableTimer()")
        public void around(ProceedingJoinPoint joinPoint) throws Throwable {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
    
            Object result = joinPoint.proceed();
    
            stopWatch.stop();
    
            System.out.println("total time : " + stopWatch.getTotalTimeSeconds());
        }
    }
    
    
    このクラスでは、@Around言語宣言を確認できます.この@Aroundメソッドは、メソッドの実行前と実行後の両方を制御できるメソッドで、主に実行時間の測定に使用されます.

    の最後の部分


    スプリング&スプリングガイドのコアコンセプトIoCとAOPを簡単に紹介した.この他にもPSAとPOJOがありますが、後で再リリースする予定です.