1.AOPとは
1 はじめに
AOPとはAspect Oriented Programmingの略で、アスペクト指向プログラミングを意味し、プリコンパイルと実行時の動的エージェントによりプログラムの機能の一元的な維持を実現する技術です。
AOP は、ソフトウェア開発のホットスポットであり、Spring フレームワークの重要なコンテンツであり、関数型プログラミングの派生パラダイムである OOP の継続です。AOP を使用すると、ビジネス ロジックのさまざまな部分を分離できるため、ビジネス ロジックのさまざまな部分間の結合が軽減され、プログラムの再利用性が向上し、開発の効率が向上します。
2. 機能とメリット
- 機能: プログラムの実行中に、ソース コードを変更することなくメソッドの機能が強化されます。
- メリット:重複コードの削減、開発効率の向上、メンテナンスの容易化
3. 基本的な実装原則
Springが提供する機能強化を実現するダイナミックプロキシ技術
(1) JDKプロキシ:インターフェースベースの動的プロキシ技術
まず簡単なターゲット インターフェイスを作成しましょう。
public interface TargetInterface {
public void save();
}
ターゲット インターフェイスを実装するために別のターゲット オブジェクトを作成しましょう。
public class Target implements TargetInterface{
@Override
public void save() {
System.out.println("save....");
}
}
最後に、拡張前と拡張後などの機能を拡張するための動的プロキシ手法を実装します。
public class ProxyTest {
public static void main(String[] args) {
//目标对象
Target target = new Target();
TargetInterface tagetInterface = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置增强...."); //前置增强
Object invoke = method.invoke(target, args); //执行目标方法
System.out.println("后置增强...."); //后置增强
return invoke;
}
});
//调用代理对象的方法
tagetInterface.save();
}
}
実行結果を見ると、メソッドが強化されていることがわかります。
(2) cglib プロキシ: 親クラスに基づく動的プロキシ技術
まずは簡単なターゲットオブジェクトを書いてみましょう
public class Target {
public void save() {
System.out.println("save running.....");
}
}
その後、動的プロキシ方式を実装して機能強化を実現します。
public class ProxyTest {
public static void main(String[] args) {
//目标对象
final Target target = new Target();
//1、创建增强器
Enhancer enhancer = new Enhancer();
//2、设置父类(目标)
enhancer.setSuperclass(Target.class);
//3、设置回调
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("前置增强....");
Object invoke = method.invoke(target, args); //执行目标
System.out.println("后置增强....");
return invoke; //返回值 就是动态生成的代理对象 基于cglib
}
});
//4、创建代理对象
Target proxy = (Target) enhancer.create();
proxy.save();
}
}
実行結果を見ると、メソッドが同じように強化されていることがわかります。
2. XMLベースのAOP開発
1. AOP関連の座標をインポートする
pom.xml を見つけて、次の 2 つの座標をインポートします。
(1) Spring のコンテキスト座標、コンテキストは aop に依存
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
(2) 側面jの統合
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.4</version>
</dependency>
2. クラスとメソッドを作成する
(1) ターゲットインターフェース
public interface TargetInterface {
public void save();
}
(2) 対象クラス(つまりカットポイント)
public class Target implements TargetInterface{
@Override
public void save() {
System.out.println("save....");
}
}
(3) アスペクトクラス(つまり拡張メソッド)
public class InvokeDemo {
public void before(){
System.out.println("前置增强....");
}
public void afterReturning(){
System.out.println("后置增强....");
}
}
3. アスペクト指向プログラミング
(1) Springにターゲットクラスとアスペクトクラスのオブジェクト作成権限を与える
applicationContext.xml を見つけて、次のコードを記述します。
<!--配置目标类-->
<bean id="target" class="com.itheima.aop.Target"></bean>
<!--配置切面类-->
<bean id="myAspect" class="com.itheima.aop.MyAspect"></bean>
(2) applicationContext.xmlでウィービング関係を設定し、
まず、aop 名前空間をインポートします。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
次に、ポイントカット式と事前拡張ウィービング関係を構成します。
まず一般的な形式を記述します。
<aop:config>
<aop:aspect ref=“切面类”>
<aop:before method=“通知方法名称” pointcut=“切点表达式"></aop:before>
</aop:aspect>
</aop:config>
ここでのポイントカット式の記述方法に注意してください。
実行([修飾子] 戻り値の型 パッケージ名.クラス名.メソッド名(パラメータ))
- アクセス修飾子は省略可能
- 戻り値の型、パッケージ名、クラス名、およびメソッド名には、アスタリスク * を使用して任意の値を表すことができます。
- パッケージ名とクラス名の間にある 1 つのドット 現在のパッケージの下のクラスを表します 2 つのドット 現在のパッケージとそのサブパッケージの下のクラスを表します
- パラメータ リストでは、2 つのドットを使用して、任意の数および任意のタイプのパラメータ リストを表すことができます。
通知タイプ:
ポイントカット式の抽出:
複数の拡張ポイントカット表現が同じである場合、ポイントカット表現を抽出でき、抽出されたポイントカット表現を参照するために拡張のpointcut属性の代わりにpointcut-ref属性が使用されます。
たとえば、以下の完全な書き込みメソッドでは、ポイントカットに myPointCut という名前を付けて <aop:aspect ... /> タグに配置し、通知前または通知後の pointcut-ref="myPointCut" から直接呼び出します。下に。
最後に、構成ポイントカット式と事前拡張ウィービング関係を完全に書き出します。
<!--配置织入-->
<aop:config>
<!--声明切面-->
<aop:aspect ref="myAspect">
<aop:pointcut id="myPointCut" expression="execution(* aop.*.*(..))"/>
<!--切面:切点+通知-->
<aop:before method="before" pointcut-ref="myPointCut"/>
<!--<aop:after method="afterReturning" pointcut="execution(public void aop.Target.save())"/>-->
<aop:after-returning method="afterReturning" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>-->
4. テスト
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test1(){
target.save();
}
}
操作結果:
このようにして、XML ベースの AOP 開発が実現しました。ただし、通常は、より便利なアノテーション開発を使用します。
3. アノテーションベースの AOP 開発
1. AOP関連の座標をインポートする
XML開発と全く同じ
2. クラスとメソッドを作成する
(1) ターゲットインターフェースとターゲットクラスの作成(XML開発と同様)
// 目标接口
public interface TargetInterface {
public void save();
}
// 目标类(也就是切点)
// @Component("target")
public class Target implements TargetInterface{
@Override
public void save() {
System.out.println("save....");
}
}
ここのポイントカット クラスは、以下で説明する @Component() アノテーションも使用できるかどうかに注意してください。
(3) セクションの種類
まず、 @Component() @Pointcut() @Aspect() アノテーションを使用する必要があります。
- @Component(): Bean インジェクションを実装する
- @Pointcut(): アスペクト式の抽出
- @Aspect(): 現在のクラスがアスペクト クラスであることを示します
@Component("myAspect")
@Aspect //标注切面类
public class MyAspect {
@Pointcut("execution(* aop.*.*(..))") // 抽取切面表达式
public void pointCut(){};
@Before("MyAspect.pointCut()")
public void before(){
System.out.println("前置增强....");
}
@AfterReturning("MyAspect.pointCut()")
public void afterReturning(){
System.out.println("后置增强....");
}
}
次に、メソッドのアノテーションを通知します。
3. 構成ファイルでコンポーネントのスキャンと AOP 自動プロキシを有効にする
applicationContext.xml ファイルを開き、XML ベースの AOP 開発をコメント アウトして、次の 2 行の構成を追加します。
Base-packageの値は、スキャンする必要があるアスペクトとポイントカット クラスが配置されているパッケージです。
<!--组件扫描-->
<context:component-scan base-package="aop"/>
<!--aop自动代理-->
<aop:aspectj-autoproxy/>
4. テスト
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Autowired
private TargetInterface target;
@Test
public void test1(){
target.save();
}
}
テスト コードを作成することで、メソッドの拡張機能を確認して実装できます。