AOPおよび実装方法の理解

16646 ワード

AOPって何?
切面プログラミング向けに、業務とは関係なく、業務モジュールに共通に呼び出された論理を重いモジュールにカプセル化します.すなわち、切面は「横断」技術を使用し、AOPはソフトウェアシステムを2つの部分に分けます.コア注目点と横断注目点です.業務処理の主な流れは核心的な注目点であり、それとあまり関係のない部分は横断的な注目点である.
なぜAOPを使うのですか?
オブジェクト向けプログラミングは、需要機能を異なる相対的に独立し、良好なクラスをカプセル化し、独自の行為を持ち、継承や多態などによって互いの関係を定義することに注目しているとすれば.では,接面プログラミングは,汎用需要機能が関連しないクラスから分離され,多くのクラスが1つの動作を共有できることを望んでおり,変化が生じると多くのクラスを修正する必要がなく,この動作を修正するだけでよい.
次のように、mulとdivの2つの方法があります.この2つの方法のコンテンツコードの多くは重複しているので、新しい方法を抽出することができます.
package com.zzj.calculatar.service;
import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService{

    @Override
    public int mul(int a, int b) {
        System.out.println("The mul method begins.");
        System.out.println("The mul method args:["+a+","+b+"]");
        return a*b;
    }

    @Override
    public int div(int a, int b) {
        System.out.println("The div method begins.");
        System.out.println("The div method args:["+a+","+b+"]");
        return a/b;
    }
    
}

新しい方法は次のとおりです.
@Service
public class CalculatorService implements ICalculatorService{

    @Override
    public int mul(int a, int b) {
        t("mul", a, b);
        return a*b;
    }

    @Override
    public int div(int a, int b) {
        t("div", a, b);
        return a/b;
    }
    
    private void t(String methodName,int a,int b){
        System.out.println("The"+methodName+"method begins.");
        System.out.println("The"+methodName+"method args:["+a+","+b+"]");
    }
    
}

AOPの切面化はここに現れ,具体的なAOP実現方式は注釈とXML配置である.
package com.zzj.calculatar.service;
import org.springframework.stereotype.Service;

@Service
public class CalculatorService implements ICalculatorService{

    @Override
    public int mul(int a, int b) {
        return a*b;
    }

    @Override
    public int div(int a, int b) {
        return a/b;
    }
    
}

注記方式でAOPを実現する:
package com.zzj.aspect;

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.core.annotation.Order;
import org.springframework.stereotype.Component;


@Order(1)//
@Aspect
@Component
public class CalculatorAspect {

        //     
    @Pointcut("execution(public int com.zzj.calculatar.service.CalculatorService.*(..))")
    public void pointCut(){
        
    }
    
    @Around(value="pointCut()")
    public Object around(ProceedingJoinPoint joinPoint){
        Object result = null;
        Object target = joinPoint.getTarget();//    
        String methodName = joinPoint.getSignature().getName();
        Object[] params = joinPoint.getArgs();
        
        try{
            try{
                //    
                System.out.println(target.getClass().getName()+": The "+methodName+" method begins.");
                System.out.println(target.getClass().getName()+": Parameters of the "+methodName+"method: ["+params[0]+","+params[1]+"]");
                //          
                result = joinPoint.proceed();
            }finally{
                //    
                System.out.println(target.getClass().getName()+":The "+methodName+" method ends.");
            }
            //    
            System.out.println(target.getClass().getName()+":Result of the "+methodName+" method:"+result);
        }catch (Throwable e) {
            System.out.println(target.getClass().getName()+":Exception of the method "+methodName+": "+e);
        }
        return result;
    }
    
}    

<context:component-scan base-package="com.zzj">context:component-scan>
<aop:aspectj-autoproxy>aop:aspectj-autoproxy>

XML構成方式はAOPを実現する(注釈を必要とせず、注釈をXMLに入れる):
package com.zzj.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
public class CalculatorAspect {
    public Object around(ProceedingJoinPoint joinPoint){
        Object result = null;
        Object target = joinPoint.getTarget();//    
        String methodName = joinPoint.getSignature().getName();
        Object[] params = joinPoint.getArgs();
        
        try{
            try{
                //    
                System.out.println(target.getClass().getName()+": The "+methodName+" method begins.");
                System.out.println(target.getClass().getName()+": Parameters of the "+methodName+"method: ["+params[0]+","+params[1]+"]");
                //          
                result = joinPoint.proceed();
            }finally{
                //    
                System.out.println(target.getClass().getName()+":The "+methodName+" method ends.");
            }
            //    
            System.out.println(target.getClass().getName()+":Result of the "+methodName+" method:"+result);
        }catch (Throwable e) {
            System.out.println(target.getClass().getName()+":Exception of the method "+methodName+": "+e);
        }
        return result;
    }
}

<context:component-scan base-package="com.zzj">context:component-scan>

<bean id="calculatorAspect" class="com.zzj.aspect.CalculatorAspect">bean>

<aop:config>
        
    <aop:pointcut expression="execution(public int com.zzj.calculatar.service.CalculatorService.*(..))" id="pointCut"/>
        
    <aop:aspect ref="calculatorAspect" order="1">
        <aop:around method="around" pointcut-ref="pointCut"/>
    aop:aspect>
aop:config>

テストクラス:
package com.zzj.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zzj.calculatar.service.ICalculatorService;

public class Test {

    public static void main(String[] args){
        
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
        System.out.println(calculatorService.getClass());//
        System.out.println(calculatorService.div(1,1));
        applicationContext.close();
        
    }
    
}

テスト結果: