AspectJの持つ春AOP

簡単な紹介

AspectJのは、JavaベースのAOPフレームワーク、AspectJの発現ポイントカット用Spring2.0後で追加支持体です。Spring1.0はAspectJのはまだ来ていたときからです。

注釈のサポートを追加でAspectJ1.5は、Beanクラスで直接定義セクションを可能にします。ビルドにSpringフレームワークの新バージョンでは、
我々はAOPを開発するためのAspectJの方法を使用して提案し、カットオフポイントの非常に柔軟で強力な表現を提供します。

もちろん、関係なく、春AOPまたはAspectJの関連する概念のと同じです。

Notes構成

輸入依存度:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>

通知タイプ

提供される通知の@AspectJタイプ:

  1. アドバイスの前に@Beforeは、実行の元のメソッドの前に実行されます

  2. 元のメソッドの前に実行されるポスト通知を@AfterReturningが行われます

  3. @Around元の通知方法の傍受の周りに完全に行われ、実行ロジック後に増加することができ、この方法は、原稿を行わなくてもよいです

  4. 通知を投げたときに、元のメソッドが異常実行する実行@AfterThrowing

  5. 最終的な最終的な通知@After、かどうかにかかわらず、例外の、元のメソッド呼び出しの後に実行されます

  6. @DeclareParentsが通知を紹介し、IntroductionInterceptorの同等(理解します)

定義されたカットポイント

タンジェントポイントは、関数の実行によって定義されます

構文:実行(アクセス修飾子の戻り値の型メソッド名パラメータ・エラー)

例式:

クラスは、すべてのパブリックメソッドと一致します。execution(public * *(..))最初のものを.. *は、戻り値は任意の型の任意のパラメータを表し

:指定したパッケージと一致するすべてのメソッドの下でexecution(* cn.xxx.dao.*(..))最初にあなたが権限と*を無視したいが、戻り値の型を示し、

:指定したメソッドに一致するすべてのパケットの下にexecution(* cn.xxx.dao..*(..))サブパケットを含み

すべてのメソッドのために指定されたクラスをマッチング: execution(* cn.xxx.service.UserService.*(..))

すべてのクラスは、特定のインターフェイスメソッドを実装マッチします: execution(* cn.xxx.dao.GenericDAO+.*(..))

全ての試合は、保存の方法で始まります。 execution(* save*(..))

アドバイスの前に

ポンポン依存:

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.2.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.2.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

AOP名前空間とXSDを追加するには、XMLの必要性:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--    启用aspectj    -->
    <aop:aspectj-autoproxy/>
<!--    目标-->
    <bean id="personDao" class="com.yh.demo1.PersonDao"/>
<!--    切面-->
    <bean class="com.yh.demo1.MyAspect"/>
</beans>

テスト:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test1 {
    @Autowired
    PersonDao personDao;

    @Test
    public void test(){
        personDao.delete();
        personDao.update();
    }
}

セクションのカテゴリ:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyAspect {
      //表示PersonDao下所有方法都作为切点
    @Before(value = "execution(* com.yh.demo1.PersonDao.*(..))")
    public void beforeAdvice(){
        System.out.println("before code run.....");
    }
}

我々は(コードを強化すること)カット点情報を取得する必要があるときは、通知にパラメータを追加することができ、私は次のだと思います

@Aspect
public class MyAspect {
    @Before(value = "execution(* com.yh.demo1.PersonDao.*(..))")
    public void beforeAdvice2(JoinPoint point){
        System.out.println("before code run2....." + point);
    }
}

アドバイスを返す後:

//当需要获取原始方法的返回值时可以在注解中添加returning参数来指定参数名  Aspectj会自动将返回值放到参数中
@AfterReturning(value = "execution(* com.yh.demo1.PersonDao.delete(..))",returning = "result")
public void afterAdvice(Object result){
    System.out.println("删除方法执行后 .....   返回值为:"+ result);
}

によって返された目標値を得ることができるリア通知

アドバイス周り:

@Around(value = "execution(* com.yh.demo1.PersonDao.insert(..))")
public void aroundAdvice(ProceedingJoinPoint point) throws Throwable {
    //code............
    System.out.println("环绕前置..");

    //执行原始方法 __当需要获取返回值时可以声明变量接收
    Object result = point.proceed();
    System.out.println("原始方法返回值: "+result);
    //code............
    System.out.println("环绕后置..");
}

助言や他の通知の周りの最大の違いは、アドバイスの周りにあるオリジナルのメソッドを呼び出すかどうかを制御することができます

注:パラメータタイプはProceedingJoinPointである必要があり、そうでない場合は、元のメソッドを実行することができません、

異常の通知

@AfterThrowing(value = "execution(* com.yh.demo1.PersonDao.save(..))",throwing = "e")
public void exceptionHandler(JoinPoint point,Exception e){
    System.out.println(point + " 方法出现"+e.getMessage()+"异常");
}

例外情報を取得する必要がある場合場合は、実装は、通知プロセスが発生するの、あなたがコメントにパラメータ名を指定して投げを追加することができます

トランザクションをコミットし、我々は、ハンドルデータベーストランザクションにだけでなく、開いているトランザクションの周りにバック例外通知ロールトランザクションをサラウンド+例外通知を使用することができ、もちろん、春の業務パッケージになっている記述する必要はありません。

最終通告

@After(value = "execution(* *delete(..))")
public void afterRun(){
    System.out.println("最终");
}

オリジナルのメソッド呼び出しにちなんで命名された最終的な通知にかかわらず、例外が元のメソッドで発生したか否かの実行後

そして、設定afterReturningが唯一成功した復帰後表し、実行と呼ばれます

論理演算子と式:

論理式にして、ユーザはオペレータを操作することができ&&、または||!

例:

/*
execution(* cn.xxx.service.UserDao.insert(..))||execution(* cn.xxx.service.UserDao.delete(..))

execution(* cn.xxx.service.UserDao.*nsert(..))&&execution(* cn.xxx.service.UserDao.inser*(..))

!execution(* cn.xxx.service.UserDao.insert(..))
*/

カットポイントの名前は

より多くの通知は、カットオフポイント、メンテナンスが非常に面倒であるとき、我々はによってカットオフポイントに名前を割り当てることができます変更する必要が変更するために、カットオフポイントで同じアプリケーション内に複数の通知があると仮定し、我々はライト実行式を繰り返す必要があり、それに続きますこうして開発とメンテナンスの効率を向上させるために、カットオフポイントの再使用と均一動作を完了する。

//定义命名切点  方法名称即切点名称
@Pointcut(value = "execution(* com.yh.demo1.PersonDao.save(..))")
private void savePointcut(){}

@Pointcut(value = "execution(* com.yh.demo1.PersonDao.delete(..))")
private void deletePointcut(){}

複数の通知は、同じカットオフ点に適用されます。

//使用命名切点
@Before(value = "savePointcut()")
public void beforeAdvice(){
    System.out.println("before code run.....");
}
//使用命名切点
@Around(value = "savePointcut()")
public void beforeAdvice2(ProceedingJoinPoint point) throws Throwable {
    System.out.println("环绕前");
    point.proceed();
    System.out.println("环绕后");

切断複数の点への通知アプリケーション

//同一个通知对应多个切点
@After(value = "savePointcut()||deletePointcut()")
public void afterAdvice(){
    System.out.println("after code run.....");
}

XML配置

XML設定に必要なjarファイルおよびさまざまなオブジェクトと式の間の依存関係は、同じ文言、それを書くだけで、別の方法です。

XML:

        <!--目标-->
    <bean id="studentDao" class="com.yh.demo2.StudentDao"/>
        <!--通知-->
    <bean id="advices" class="com.yh.demo2.XMLAdvice"/>

        <!--织入信息-->
    <aop:config>
                <!--切点定义-->
        <aop:pointcut id="select" expression="execution(* com.yh.demo2.StudentDao.select(..))"/>
                <!--切面定义-->
        <aop:aspect ref="advices">
            <aop:before method="before" pointcut-ref="select"/>
            <aop:after-returning method="afterReturning" pointcut-ref="select" returning="result"/>
            <aop:after method="after" pointcut-ref="select" />
            <aop:after-throwing method="exception" pointcut-ref="select" throwing="e"/>
            <aop:around method="around" pointcut-ref="select"/>
        </aop:aspect>
      
        <!--入侵式通知 即通知需要实现指定接口 两种不能同时使用 -->
        <aop:advisor advice-ref="advice2" pointcut-ref="select"/>
    </aop:config>
  <!--入侵式通知Bean-->
  <bean id="advice2" class="com.yh.demo2.XMLAdvice2"/>

通知の種類:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.JoinPoint;

public class XMLAdvice {
    public void before(JoinPoint pointcut){ System.out.println("前置通知 切点:"+pointcut); }

    public void afterReturning(JoinPoint point,Object result){
        System.out.println("后置通知 切点:"+point);
    }

    public void after(JoinPoint point){ System.out.println("最终通知 切点:"+point); }

    public void exception(JoinPoint point,Throwable e){
        System.out.println("异常通知: " + e+"切点:"+point);
    }

    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕前");
        point.proceed();
        System.out.println("环绕后");
    }
}

あなたはそれがXMLまたは注釈手動プロキシだけでなく、ターゲットオブジェクトを指定する必要はありませんかどうかを、AspectJのは、ターゲットオブジェクトの接点から情報を取得し、自動的にプロキシが作成されます、わかります。

AspectJのは、現在のプロジェクトの特定のニーズに基づいてXMLまたは注釈を使用して、より一般的な方法であり、パネルは、共同開発のXMLをお勧めします。

おすすめ

転載: www.cnblogs.com/yangyuanhu/p/12180732.html