AOP
AOPとは
アスペクト指向プログラミング。実行時のプリコンパイルと動的エージェントにより、プログラム機能の統一保守を実現する技術。AOPはOOPの続きであり、ソフトウェア開発のホットスポットであり、Springフレームワークの重要なコンテンツです。関数型プログラミングの派生ジェネリックです。AOPを使用すると、ビジネスロジックのさまざまな部分を分離できるため、ビジネスロジックが作成されます。各部の結合度が低下し、プログラムの再利用性が向上すると同時に、開発効率も向上します。
春のAOPの役割
- 宣言型トランザクションを提供し、ユーザーがアスペクトをカスタマイズできるようにします
コア名詞
- 横断的関心事:アプリケーションの複数のモジュールにまたがるメソッドまたは関数。つまり、ビジネスロジックとは何の関係もありませんが、注意が必要なのは、ログ、セキュリティ、キャッシュ、トランザクションなどの横断的関心事です。
- 側面:横断的な焦点がモジュール化されている特徴的なオブジェクト、すなわち:それはクラスです
- 注意:セクションで実行する必要のある作業。つまり、それはクラスのメソッドです
- ターゲット:通知される
- プロキシ:将来作成されるオブジェクトをターゲットオブジェクトアプリケーションに通知します。
- エントリポイント:アスペクト通知を実装するための「場所の定義」
- 接続ポイント:エントリポイントと一致する実行ポイント
Springでサポートされる5種類のアドバイス
通知タイプ | ジャンクション | インターフェイスを実装する |
---|---|---|
予告 | メソッドの前 | MethodBeforeAdvice |
通知を投稿する | メソッドの後 | AfterReturningAdvice |
サラウンド通知 | メソッドの前後 | MethodInterceptor |
例外スロー通知 | メソッドは例外をスローします | ThrowsAdvice |
紹介通知 | クラスに新しいメソッド属性を追加します | はじめにOnterceptor |
つまり、Aopは元のコードを変更せずに新しい関数を追加します
Springを使用してAopを実装する
AOPを使用するには、依存関係パッケージをインポートする必要があります
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
最初の方法-SpringAPIを介して
ビジネスインターフェイスと実装クラス
public interface UserService {
public void add();
public void delete();
public void update();
public void search();
}
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void update() {
System.out.println("更新用户");
}
@Override
public void search() {
System.out.println("查询用户");
}
}
強化されたクラス
事前拡張
public class Log implements MethodBeforeAdvice {
//method : 要执行的目标对象的方法
//objects : 被调用的方法的参数
//Object : 目标对象
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被执行了");
}
}
ポストエンハンスメント
public class AfterLog implements AfterReturningAdvice {
//returnValue 返回值
//method被调用的方法
//args 被调用的方法的对象的参数
//target 被调用的目标对象
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了" + target.getClass().getName()
+"的"+method.getName()+"方法,"
+"返回值:"+returnValue);
}
}
Springファイルに移動して、aopカットイン実装を登録および実装します
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!--注册bean-->
<bean id="userService" class="com.zhonghu.service.UserServiceImpl"/>
<bean id="log" class="com.zhonghu.log.Log"/>
<bean id="afterLog" class="com.zhonghu.log.AfterLog"/>
<!--aop的配置-->
<aop:config>
<!--切入点 expression:表达式匹配要执行的方法 -->
<aop:pointcut id="pointcut" expression="execution(* com.zhonghu.service.UserServiceImpl.*(..))"/>
<!--执行环绕增强; advice-ref执行方法 . pointcut-ref切入点-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
テスト
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 动态代理代理的是接口
UserService userService = (UserService) context.getBean("userService");
userService.search();
}
}
Aopの重要性:非常に重要です。アイデアを理解する必要があります
Spring'sAopは、パブリックビジネス(ロギング、セキュリティ)とドメインビジネスを組み合わせることです。ドメインビジネスを実行すると、パブリックビジネスが追加され、パブリックビジネスの再利用が実現します。ドメインビジネスはより純粋で、プログラマーはフィールドビジネスに集中するだけで済みます。 。
その本質は依然として動的エージェントです
2番目の方法:Aopを達成するためのカスタムクラス
ターゲットビジネスはuserServiceImplと同じままです
クラスにカット
public class DiyPointcut {
public void before(){
System.out.println("---------方法执行前---------");
}
public void after(){
System.out.println("---------方法执行后---------");
}
}
スプリング構成に移動
<!--第二种方式自定义实现-->
<!--注册bean-->
<bean id="diy" class="com.zhonghu.config.DiyPointcut"/>
<!--aop的配置-->
<aop:config>
<!--第二种方式:使用AOP的标签实现-->
<aop:aspect ref="diy">
<aop:pointcut id="diyPonitcut" expression="execution(* com.zhonghu.service.UserServiceImpl.*(..))"/>
<aop:before pointcut-ref="diyPonitcut" method="before"/>
<aop:after pointcut-ref="diyPonitcut" method="after"/>
</aop:aspect>
</aop:config>
テスト
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}
3番目の方法-注釈を使用する
アノテーション実装用の拡張クラス
package com.zhonghu.config;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
// 标注这个类是一个切面
// 标注这个类是一个切面
@Aspect
public class PointCut {
@Before("execution(* com.zhonghu.pojo.User.*(..))")
public void befer(){
System.out.println("方法执行前");
}
@After("execution(* com.zhonghu.pojo.User.*(..))")
public void after(){
System.out.println("方法执行后");
}
//在环绕增强中,我们可以给定一个参数,代表我们要处理切入的点。
@Around("execution(* com.zhonghu.pojo.User.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
System.out.println("签名:"+jp.getSignature());
//执行目标方法proceed
Object proceed = jp.proceed();
System.out.println("环绕后");
System.out.println(proceed);
}
}
Spring構成ファイルで、Beanを登録し、アノテーションをサポートする構成を追加します
<!--第三种方式:注解实现-->
<bean id="annotationPointcut" class="com.zhonghu.config.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>
出力結果:
アスペクトの実行順序:
aop:aspectj-autoproxy:説明
- aopによって作成された名前空間の<aop:aspectj-autoproxy />宣言は、Springコンテナー内の@aspectJアスペクトで構成されたBeanのプロキシーを自動的に作成し、アスペクトに織り込みます。もちろん、Springは引き続きAnnotationAwareAspectJAutoProxyCreatorを内部的に使用して自動プロキシを作成しますが、特定の実装の詳細は<aop:aspectj-autoproxy />によって隠されています。
- <aop:aspectj-autoproxy />にはproxy-target-class属性があり、デフォルトはfalseです。これは、<aop:aspectj-autoproxy poxy-target-class = "trueとして構成されている場合、jdk動的プロキシウィービング拡張機能を使用することを意味します。 "/>当時、それはCGLib動的プロキシテクノロジーを使用して織り込み、強化することを意味します。ただし、proxy-target-classがfalseに設定されている場合でも、ターゲットクラスがインターフェイスを宣言していない場合、Springは自動的にCGLib動的プロキシを使用します。
やっと
- 読んでやりがいを感じたら、いいねをあげたいと思います。これが更新の最大のモチベーションになります。ご支援ありがとうございます。
- Javaとコンピュータの基本的な知識に焦点を当てた私の公開アカウント[JavaFox]に注目してください。私を信じていない場合は、私を叩いてください。
- 読んだ後に異なる意見や提案がある場合は、コメントして私たちと共有してください。皆様のご支援、ご愛顧を賜りますようお願い申し上げます。
最新ニュースについては、パブリックアカウント「JavaFox」をフォローすることを歓迎します