SpringAOP原理分析

ディレクトリ

春のコア知識

SpringAOP原則

AOPプログラミング

AOPプログラミングは何ですか

AOP原則基本的な実装

AOPを使ったプログラミング


 

春のコア知識

春はオープンソースのフレームワークの春2003のJava開発フレームワーク、派生彼の本の専門家一対一のJ2EE開発・設計・試作にロッド・ジョンソンが定める哲学の一部で軽量な上昇です。作成したエンタープライズアプリケーション開発の複雑さに対処するように設計されています。フレームワークの主な利点の一つは、その階層化アーキテクチャは、階層化アーキテクチャは同様にJ2EEアプリケーション開発は、統合フレームワークを提供し、ユーザが使用するコンポーネントを選択することを可能にします。春は以前のみ可能EJBで物事を行うための基本的なJavaBeansを使用しています。しかし、Springの使用は、サーバー側の開発に限定されるものではありません。任意のJavaアプリケーションは、春の観点から単純、テスト容易性と疎結合から利益を得ることができます。コアは、コントロールの春反転(IOC)と対向する部分(AOP)です。簡潔には、スプリングは、層状するJavaSE / EEfullスタック(停止)軽量オープンソースフレームワークです。

なぜ春の軽量オープンソースのフレームワークは、それを停止されましたか?EEの開発者は、各層ばねが異なる溶液の技術を提供して、3層構造のJavaEEのための3階層アーキテクチャに分割することができます。

•WEB層:SpringMVC

•ビジネスレイヤ:SpringのIoCの

•永続層:JDBCTemplateの春(SpringのJDBCテンプレート、他の永続化フレームワークを統合するためのORMテンプレート)

上記の簡単な説明から、我々はコア春は2つの部分を持って知っておく必要があります。

•のIoC:制御の反転。

例えば、操作の前に、我々はメソッド(静的メソッドではない)内のクラスを呼びたい、クラスがあると言って、オブジェクトクラスを作成するメソッドを呼び出すためにオブジェクトを使用する必要があります。コードで実装されていませんが、Spring構成に達成するために春、オブジェクトの春の作成について。

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

SpringAOP原則

AOPプログラミング

 

AOPプログラミングは何ですか

AOP:アスペクト指向プログラミングアスペクト指向プログラミング。(また、アスペクト指向と呼ばれる)アスペクト指向プログラミング:アスペクト指向プログラミング(AOP)は 、 ソフトウェア開発のホットスポットです。AOPは、開発の効率を向上させつつ、ビジネス・ロジックは、プログラムの再利用性を向上させ、部品間の結合の程度を低減するようなビジネス・ロジックの各部分を分離するために使用することができます。AOPはOOPの継続は、その切断面(側面)のプログラミングを意味する、(アスペクト指向プログラミング)の頭字語です。主な機能は以下のとおりです。ログ、パフォーマンス統計、セキュリティ管理、トランザクション処理、例外処理ように、と。主な目的は次のとおりです。ログ、パフォーマンス統計、セキュリティ管理、トランザクション処理、例外処理コードは、これらのアクションを分離することにより、ビジネスロジックコードから分割され、我々は、彼らが独立非方法論ガイダンスビジネスロジックなることを願ってで、その後、時間の動作を変更するには、ビジネス・ロジック・コードには影響を与えません。

 

  ソースコードを変更せずに機能を追加するために動的に統一されたプログラムのための一つの技術は、プリコンパイルされた動的プロキシモードと実行することによって達成することができます。AOPは、実際に呼び出し元と呼び出し先の間のデカップリングのGoFのデザインパターン、デザインパターンのたゆまぬ追求の継続で、AOPは、この問題をこの目的の実現であると言うことができます。

三次元構造のアプリケーション考えると仮定する、次いで、OOPかみそりの長手方向のカットシステムであり、システムは(例えば:などのユーザモジュール、物品モジュール)モジュールの数に分割され、AOPかみそり横切断システムは、各モジュールの抽出いくつかは(:パーミッション・チェック、ログ、等のような)の操作を繰り返してもよいです。したがって、AOPはOOPの効果的な補数です。

注意:AOPは技術ではない、実際にアイデアをプログラミングします。AOP思考技術を満たした者は、AOPを実現するためにとして見ることができます。

 

AOP、アスペクト指向プログラミングオブジェクトプログラミング

機能:ビジネスコードから別のコードの懸念をしてみましょう!

フォーカス

懸念、重複したコードが懸念と呼ばれています。

セクション

セクション(クラス)と呼ばれるクラスのフォーカス形成、!

指向プログラミングは、他のネットワークサービスの動的インプラント上で動作しているとき、多くの機能は、抽出コードを繰り返しているを意味し、「クラスのコードセクション。」

エントリー・ポイント

実行対象オブジェクトメソッド、DYNAMICインプラント部分をコードします。

実行時に指定したクラスのクラスコードにインプラントカット、どのクラスインターセプト方法を指定するポイントカット表現で。

AOP原則基本的な実装

プロキシデザインパターン

プロキシモードとは何ですか

メソッドプロキシのアクセス制御を経由オブジェクトは、この後のコール処理方法では、オブジェクトの詳細にアクセス、または処理を呼び出すことができます。どちらも(AOPマイクロが実現)、AOPアスペクト指向プログラミングのコア技術。

 

プロキシモードのシナリオ

SpringAOPは、物事の原理は、印刷、アクセス制御、リモート呼び出しをログに記録し、セキュリティエージェントは、真の役割を隠すこと

演技の分類

静的剤(静的に定義されたプロキシクラス)

ダイナミックプロキシ(動的に生成されたプロキシクラス)

JDKは、動的プロキシが付属しています

CGLIB、javaassist(バイトコード操作ライブラリ)

帯電防止剤

帯電防止剤は何ですか

プロキシクラスのソースコードを生成して、プロキシクラスをコンパイルするプログラマやツールによって作成されました。プログラムは、既存の関係のバイトコードファイル上で実行される前に、静的いわゆる、実行する前に、プロキシクラスと委譲クラスのプロキシクラスが決定されます。

 

静的エージェント・コード

public interface IUserDao {
    void save();
}
public class UserDao implements IUserDao {
    public void save() {
        System.out.println("已经保存数据...");
    }
}
代理类
public class UserDaoProxy implements IUserDao {
    private IUserDao target;
​
    public UserDaoProxy(IUserDao iuserDao) {
        this.target = iuserDao;
    }
​
    public void save() {
        System.out.println("开启事物...");
        target.save();
        System.out.println("关闭事物...");
    }
​
}

動的プロキシ

 

 

ダイナミックエージェントとは何ですか

1.プロキシオブジェクト、インターフェースを実装する必要はありません

2.メモリに動的プロキシオブジェクトを構築し、JDKのAPIを使用して、プロキシオブジェクトを生成する(プロキシオブジェクト/ターゲット・オブジェクトの実装を作成するために、インターフェイスのタイプを指定するために私達を必要とします)

JDKエージェント、インタフェースエージェント:としても知られている3.ダイナミックエージェント

JDKダイナミックプロキシ

1)原理:クラスローダが作成され、プロキシクラスインターフェース(プロキシクラスが実装クラスインターフェースであるので、インタフェースはjava.lang.reflectのパッケージに位置するインターフェイス発生剤のために使用されなければなりません)

2)の方法:

  1. あなた自身の呼処理IvocationHandlerハンドラ=新しいInvocationHandlerImpl(...)を作成するためのインタフェースを実装することでのInvocationHandler。

  2. インタフェースオブジェクトのセットを指定することにより、動的プロキシクラスクラスclazzのクラスローダを作成し、プロキシクラスの= Proxy.getProxyClass(クラスローダ、新しいクラス[] {...})。

  3. パラメータタイプは、呼プロセッサインタフェースタイプコンストラクタコンストラクタ= clazz.getConstructor(新しいクラス[] {InvocationHandler.class})で反射による動的プロキシクラスのコンストラクタを取得します。

  4. この場合のプロキシクラスのインスタンスコンストラクタを呼び出し作成することによって、パラメータハンドラオブジェクトインタフェースプロキシ=(インタフェース)constructor.newInstance(新しいオブジェクト[](ハンドラ))として渡される必要があります。

欠点:JDKの動的プロキシは、インターフェイスを実装する必要があり、ターゲットのビジネスクラスへのインタフェースを重視しなければなりません

// 每次生成动态代理类对象时,实现了InvocationHandler接口的调用处理器对象 
public class InvocationHandlerImpl implements InvocationHandler {
    private Object target;// 这其实业务实现类对象,用来调用具体的业务方法
    // 通过构造函数传入目标对象
    public InvocationHandlerImpl(Object target) {
        this.target = target;
    }
​
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        System.out.println("调用开始处理");
        result = method.invoke(target, args);
        System.out.println("调用结束处理");
        return result;
    }
​
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        // 被代理对象
        IUserDao userDao = new UserDao();
        InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDao);
        ClassLoader loader = userDao.getClass().getClassLoader();
        Class<?>[] interfaces = userDao.getClass().getInterfaces();
        // 主要装载器、一组接口及调用处理动态代理实例
        IUserDao newProxyInstance = (IUserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl);
        newProxyInstance.save();
    }
​
}

CGLIB動的プロキシ

原理:オープンソースパッケージを使用して、ASM、クラスファイルのプロキシオブジェクトクラスは、サブクラスのバイトコードを変更することによって処理され、中にロードされました。

ダイナミックプロキシは何ですかCGLIB

CGLIBを使用し、[コード生成ライブラリ]ダイナミックエージェント、基本的なフレームワークのASMは、バイトコード生成されたプロキシクラスのバイトコードを生成し使用して、インターフェイスを実装する必要があり委譲クラスを必要としません。

CGLIB動的プロキシ関連するコード

public class CglibProxy implements MethodInterceptor {
    private Object targetObject;
    // 这里的目标类型为Object,则可以接受任意一种参数作为被代理类,实现了动态代理
    public Object getInstance(Object target) {
        // 设置需要创建子类的类
        this.targetObject = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
​
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开启事物");
        Object result = proxy.invoke(targetObject, args);
        System.out.println("关闭事物");
        // 返回代理对象
        return result;
    }
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDao());
        userDao.save();
    }
}
​

JDK CGLIB間の動的プロキシ動的な差

処理するために、特定のメソッドを呼び出す前に、インタフェース・コール・InvokeHandlerを実装匿名プロキシクラスを生成するためにリフレクションを使用してJava動的プロキシ。

サブクラスのバイトコードを変更することによって処理中にロードされたオープンソースパッケージ、クラスファイルのプロキシオブジェクトクラスを使用して、ASM動的プロキシCGLIB。

春に。

図1は、ターゲットオブジェクトがインタフェースを実装している場合、デフォルトJDKダイナミックプロキシAOP実装ケースを使用します

ターゲットオブジェクトがインタフェースを実装している場合2、あなたはAOPを実現CGLIBの使用を強制することができます

インタフェースを実装していない対象物がCGLIBライブラリを使用する必要がある場合、図3に示すように、ばねが自動的にJDKダイナミックプロキシとCGLIB切り替えます

クラスに対してのみエージェントを構築することができますインターフェイスを実装し、ないJDKダイナミックプロキシクラス。CGLIB剤がクラスのために達成され、メインクラスは、サブクラス、被覆の前記方法を生成するために指定されています。それが継承され、そのクラスやメソッドをfinalとして宣言することはしないことをお勧めですので、最終的には、継承、ポリモーフィズムをブロックすることができます。

 

AOPを使ったプログラミング

 

ノートバージョンはAOPを実装します

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>  开启事物注解权限
@Aspect                         指定一个类为切面类       
@Pointcut("execution(* com.service.UserService.add(..))")  指定切入点表达式
@Before("pointCut_()")              前置通知: 目标方法之前执行
@After("pointCut_()")               后置通知:目标方法之后执行(始终执行)
@AfterReturning("pointCut_()")       返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing("pointCut_()")           异常通知:  出现异常时候执行
@Around("pointCut_()")              环绕通知: 环绕目标方法执行
​
​
@Component
@Aspect
public class AopLog {
​
    // 前置通知
    @Before("execution(* com.service.UserService.add(..))")
    public void begin() {
        System.out.println("前置通知");
    }
​
​
    // 后置通知
    @After("execution(* com.service.UserService.add(..))")
    public void commit() {
        System.out.println("后置通知");
    }
​
    // 运行通知
    @AfterReturning("execution(* com.service.UserService.add(..))")
    public void returning() {
        System.out.println("运行通知");
    }
​
    // 异常通知
    @AfterThrowing("execution(* com.service.UserService.add(..))")
    public void afterThrowing() {
        System.out.println("异常通知");
    }
​
    // 环绕通知
    @Around("execution(* com.service.UserService.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知开始");
        proceedingJoinPoint.proceed();
        System.out.println("环绕通知结束");
    }
}
​
​

 

XML AOPを実現するための方法

XML AOPプログラミング達成する:
    1)[4番目、AOP関連ジャー]をファイルジャーを導入
    2)AOP名前空間を導入する
    。3)AOPの設定
        *設定アスペクトクラス(クラスコード形式を繰り返す)
        * AOP構成
            傍受/インターセプト法を意味通知コードの適用後
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
​
    <!-- dao 实例 -->
​
    <bean id="userService" class="com.service.UserService"></bean>
    <!-- 切面类 -->
    <bean id="aop" class="com.aop2.AopLog2"></bean>
    <!-- Aop配置 -->
    <aop:config>
        <!-- 定义一个切入点表达式: 拦截哪些方法 -->
        <aop:pointcut expression="execution(* com.service.UserService.*(..))"
            id="pt" />
        <!-- 切面 -->
        <aop:aspect ref="aop">
            <!-- 环绕通知 -->
            <aop:around method="around" pointcut-ref="pt" />
            <!-- 前置通知: 在目标方法调用前执行 -->
            <aop:before method="begin" pointcut-ref="pt" />
            <!-- 后置通知: -->
            <aop:after method="after" pointcut-ref="pt" />
            <!-- 返回后通知 -->
            <aop:after-returning method="afterReturning"
                pointcut-ref="pt" />
            <!-- 异常通知 -->
            <aop:after-throwing method="afterThrowing"
                pointcut-ref="pt" />
        </aop:aspect>
    </aop:config>
​
</beans>
public class AopLog2 {
​
    // 前置通知
    public void begin() {
        System.out.println("前置通知");
    }
​
    //
    // 后置通知
    public void commit() {
        System.out.println("后置通知");
    }
​
    // 运行通知
    public void returning() {
        System.out.println("运行通知");
    }
​
    // 异常通知
    public void afterThrowing() {
        System.out.println("异常通知");
    }
​
    // 环绕通知
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知开始");
        proceedingJoinPoint.proceed();
        System.out.println("环绕通知结束");
    }
}

 

 

 

おすすめ

転載: blog.csdn.net/weixin_40160543/article/details/92010760
おすすめ