Spring AOP(

アスペクト指向プログラミング

)フレームワークは、側面でのクロスカッティングの問題をモジュール化するために使用されます。シンプルにすると、メソッドが実行されるとき、Spring AOPが実行中のメソッドをハイジャックすることができ、メソッドの実行の前後に余分な機能を追加するなど、いくつかのプロセスをインターセプトするインターセプタだけです。

Spring AOPでは、4種類のアドバイスがサポートされています:

  • アドバイス前 – メソッド実行前に実行

  • アドバイスを返した後 – メソッドが結果を返した後に実行

  • アドバイスをスローした後 – メソッドが例外をスローした後に実行

  • 周囲のアドバイス – メソッドの実行を中心に実行し、3つすべてを組み合わせる

上記のアドバイス。

次の例は、Spring AOPのアドバイスの仕組みを示しています。

簡単なSpringの例

後でデモンストレーションするための印刷方法が少ないシンプルな顧客サービスクラスを作成します。

package com.mkyong.customer.services;

public class CustomerService {
    private String name;
    private String url;

    public void setName(String name) {
        this.name = name;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void printName() {
        System.out.println("Customer name : " + this.name);
    }

    public void printURL() {
        System.out.println("Customer website : " + this.url);
    }

    public void printThrowException() {
        throw new IllegalArgumentException();
    }

}

ファイル:Spring-Customer.xml – Bean構成ファイル

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
        <property name="name" value="Yong Mook Kim"/>
        <property name="url" value="/"/>
    </bean>

</beans>

それを実行します

package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mkyong.customer.services.CustomerService;

public class App {
    public static void main(String[]args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext(
                new String[]{ "Spring-Customer.xml" });

        CustomerService cust = (CustomerService) appContext.getBean("customerService");

        System.out.println("** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ");
        cust.printName();
        System.out.println("** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ");
        cust.printURL();
        System.out.println("** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ");
        try {
            cust.printThrowException();
        } catch (Exception e) {

        }

    }
}

出力

** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **

顧客名:キムヨンムック
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
顧客のウェブサイト:/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **

A simple Spring project to DI a bean and output some Strings.

Spring AOP Advices

Now, attach Spring AOP advices to above customer service.

1. Before advice

It will execute before the method execution. Create a class which
implements MethodBeforeAdvice interface.

パッケージcom.mkyong.aop;

import java.lang.reflect.Method;インポートorg.springframework.aop.MethodBeforeAdvice;

パブリッククラスHijackBeforeMethodはMethodBeforeAdviceを実装しています
{
    @オーバーライド
    public void before(メソッドメソッド、Object[]args、Object target)
        Throwableをスローする{
            System.out.println( "HijackBeforeMethod:メソッドがハイジャックされる前に!");
    }
}

Bean設定ファイル(Spring-Customer.xml)で、

HijackBeforeMethod

クラス、および新しいプロキシオブジェクト


customerServiceProxy

‘。

  • ‘target’ – ハイジャックするBeanを定義します。

  • ‘interceptorNames’ – 適用したいクラス(アドバイス)を定義する
    このプロキシ/ターゲットオブジェクト

<beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://www .springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ">

<bean id = "customerService" class = "com.mkyong.customer.services.CustomerService"> <property name = "name" value = "Yong Mook Kim"/> <property name = "url" value = "/"/> </bean>

<bean id = "hijackBeforeMethodBean" class = "com.mkyong.aop.HijackBeforeMethod"/>

<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean">

<property name = "target" red = "customer service"/>

<property name = "interceptorNames">
            <list>
                <value> hijackBeforeMethodBean </value>
            </list>
        </property>
    </bean>
</beans>

  • 注**

    Springプロキシを使用するには、CGLIB2ライブラリを追加する必要があります。以下をMavenに追加する
    pom.xmlファイル。

<依存関係>
        <groupId> cglib </groupId>
        <artifactId> cglib </artifactId>
        <version> 2.2.2 </version>
    </dependency>

もう一度実行すると、代わりに新しい


customerServiceProxy


beanが取得されます
元々のお客様のサービス**

パッケージcom.mkyong.common;

インポートorg.springframework.context.ApplicationContext;インポートorg.springframework.context.support.ClassPathXmlApplicationContext; import com.mkyong.customer.services.CustomerService;

パブリッククラスApp(public static void main(String[]args){ApplicationContext appContext = new ClassPathXmlApplicationContext(new String[]{"Spring-Customer.xml"});

CustomerService cust =(CustomerService)appContext.getBean( "customerServiceProxy");

System.out.println( "** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** "); cust.printName(); System.out.println( "** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** "); cust.printURL(); System.out.println( "** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** "); try {cust.printThrowException(); } catch(例外e){

}

}
}

出力

** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
HijackBeforeMethod : Before method hijacked!
Customer name : Yong Mook Kim
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **

HijackBeforeMethod:メソッドがハイジャックされる前に!

顧客のウェブサイト:/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
HijackBeforeMethod:メソッドがハイジャックされる前に!

すべてのcustomerServiceのメソッドが実行される前に

HijackBeforeMethodのbefore()

メソッドが実行されます。

2.アドバイスを返した後

メソッドが結果を返した後に実行されます。

AfterReturningAdvice

インターフェイスを実装するクラスを作成します。

package com.mkyong.aop;

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;

public class HijackAfterMethod implements AfterReturningAdvice
{
    @Override
    public void afterReturning(Object returnValue, Method method,
        Object[]args, Object target) throws Throwable {
            System.out.println("HijackAfterMethod : After method hijacked!");
    }
}

Bean設定ファイル

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
        <property name="name" value="Yong Mook Kim"/>
        <property name="url" value="/"/>
    </bean>

    <bean id="hijackAfterMethodBean" class="com.mkyong.aop.HijackAfterMethod"/>

    <bean id="customerServiceProxy"
                class="org.springframework.aop.framework.ProxyFactoryBean">

        <property name="target" ref="customerService"/>

        <property name="interceptorNames">
            <list>
                <value>hijackAfterMethodBean</value>
            </list>
        </property>
    </bean>
</beans>

もう一度実行すると、出力

** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **

顧客名:Yong Mook Kim HijackAfterメソッド:メソッドがハイジャックされた後!

** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
Customer website :/HijackAfterMethod : After method hijacked!
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **

It will run the

HijackAfterMethod’s afterReturning()

method, after
every customerService’s methods that are returned result.

3. After throwing advice

It will execute after the method throws an exception. Create a class
which implements ThrowsAdvice interface, and create a

afterThrowing

method to hijack the

IllegalArgumentException

exception.

パッケージcom.mkyong.aop;

org.springframework.aop.ThrowsAdviceをインポートします。

パブリッククラスHijackThrowExceptionは、ThrowsAdvice {
    public void afterThrowing(IllegalArgumentException e)throws Throwable {
        System.out.println( "HijackThrowException:例外をハイジャックしました!");
    }
}

Bean設定ファイル

<beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://www .springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ">

<bean id = "customerService" class = "com.mkyong.customer.services.CustomerService"> <property name = "name" value = "Yong Mook Kim"/> <property name = "url" value = "/"/> </bean>

<bean id = "hijackThrowExceptionBean" class = "com.mkyong.aop.HijackThrowException"/>

<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean">

<property name = "target" ref = "customerService"/>

<property name = "interceptorNames">
            <list>
                <value> hijackThrowExceptionBean </value>
            </list>
        </property>
    </bean>
</beans>

再度実行し、出力する

** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
Customer name : Yong Mook Kim
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **

顧客のウェブサイト:/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
HijackThrowException:例外をハイジャックしました!

  • HijackThrowExceptionのafterThrowing()** メソッドを実行します。これは、customerServiceのメソッドが例外をスローした場合です。

4.周囲のアドバイス

上記の3つのアドバイスをすべて組み合わせ、メソッドの実行中に実行します。

MethodInterceptor

インタフェースを実装するクラスを作成します。元のメソッドの実行を続行するには、

“methodInvocation.proceed();

“を呼び出す必要があります。そうしないと、元のメソッドは実行されません。

package com.mkyong.aop;

import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class HijackAroundMethod implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {

        System.out.println("Method name : "
                + methodInvocation.getMethod().getName());
        System.out.println("Method arguments : "
                + Arrays.toString(methodInvocation.getArguments()));

       //same with MethodBeforeAdvice
        System.out.println("HijackAroundMethod : Before method hijacked!");

        try {
           //proceed to original method call
            Object result = methodInvocation.proceed();

           //same with AfterReturningAdvice
            System.out.println("HijackAroundMethod : Before after hijacked!");

            return result;

        } catch (IllegalArgumentException e) {
           //same with ThrowsAdvice
            System.out.println("HijackAroundMethod : Throw exception hijacked!");
            throw e;
        }
    }
}

Bean設定ファイル

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
        <property name="name" value="Yong Mook Kim"/>
        <property name="url" value="/"/>
    </bean>

    <bean id="hijackAroundMethodBean" class="com.mkyong.aop.HijackAroundMethod"/>

    <bean id="customerServiceProxy"
                class="org.springframework.aop.framework.ProxyFactoryBean">

        <property name="target" ref="customerService"/>

        <property name="interceptorNames">
            <list>
                <value>hijackAroundMethodBean</value>
            </list>
        </property>
    </bean>
</beans>

再度実行し、出力する

** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **

メソッド名:printNameメソッドの引数:[]HijackAroundMethod:メソッドがハイジャックされる前に!

顧客名:Yong Mook Kim Hijack周辺方法:ハイジャックされた後!

** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
Method name : printURL
Method arguments :[]HijackAroundMethod : Before method hijacked!
Customer website :/HijackAroundMethod : Before after hijacked!
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **

メソッド名:printThrowExceptionメソッド引数:[]HijackAroundMethod:メソッドがハイジャックされる前に!

HijackAroundMethod:例外をハイジャックしました!

It will run the


HijackAroundMethod’s invoke()


method, after every
customerService’s method execution.

Conclusion

Most of the Spring developers are just implements the ‘Around advice ‘,
since it can apply all the advice type, but a better practice should
choose the most suitable advice type to satisfy the requirements.

  • Pointcut**

    In this example, all the methods in a customer service class are
    intercepted (advice) automatically. But for most cases, you may need to
    use

    Pointcut and
    Advisor

    to intercept a method via it’s method name.

Download Source Code

Download it –

Spring-AOP-Advice-Examples.zip

(8 KB)