1.AOPの概念
(1)アスペクト指向プログラミング(アスペクト)、AOPを使用すると、ビジネスロジックのさまざまな部分を分離できるため、ビジネスロジックの
さまざまな部分間の結合が減り、プログラムの再利用性が向上し、同時に開発の効率が向上します。時間。
(2)一般的な説明:ソースコードを変更せずに、メイン関数に新しい関数を追加します。
2.AOPの基本原則
AOPは、最下層で動的プロキシを使用します。これは、2つのケース(インターフェイスありとインターフェイスなし)に分けられます。
1.インターフェースがある場合はJDK動的プロキシを使用します
2.インターフェースがない場合は、CGLIB動的プロキシを使用します
3. AOP(JDK動的プロキシ)
(これはインターフェイスの場合です。インターフェイスの実装クラスのプロキシオブジェクトを作成します-InvocationHandlerを実装し、クラスのメソッドを拡張し
ます); 1.Proxyクラスのメソッドを使用してプロキシオブジェクトを作成します。最初のオブジェクトを
呼び出します。newProxyInstanceメソッドの
パラメーター:クラスローダー;
2番目のパラメーター:拡張メソッドが配置されているクラス、このクラスが実装するインターフェイス、複数のインターフェイスをサポート;
3番目のパラメーター:このインターフェイスInvocationHandlerを実装し、プロキシオブジェクトを作成し、強化された部分
JDK動的プロキシコードのデモを作成する
1.インターフェースを作成し、メソッドを定義します
public interface UserDao {
public int add(int a,int b);
public String update(String id); }
2.インターフェイス実装クラスを作成し、メソッドを実装します
public class UserDaoImpl implements UserDao {
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String update(String id) {
return id;
}
}
3. Proxyクラスを使用して、インターフェイスプロキシオブジェクトを作成します
public class JDKProxy {
public static void main(String[] args) {
// 创建接口实现类代理对象
Class[] interfaces = {
UserDao.class};
// Proxy.newProx yInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// });
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao)Proxy. newProxyInstance (JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int result = dao.add(1, 2);
System. out .println("result:"+result);
} }
// 创建代理对象代码
class UserDaoProxy implements InvocationHandler {
//1 把创建的是谁的代理对象,把谁传递过来
// 有参数构造传递
private Object obj;
public UserDaoProxy(Object obj) {
this.obj = obj;
}
// 增强的逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 方法之前
System. out .println("方法之前执行...."+method.getName()+" :传递的参 数..."+ Arrays. toString (args));
// 被增强的方法执行
Object res = method.invoke(obj, args);
// 方法之后
System. out .println("方法之后执行...."+obj);
return res;
}
}
4.AOPの用語
1
连接点
。:クラス内のどのメソッドを拡張できるか、これらのメソッドは接続ポイントと呼ばれます
。2切入点
。:実際に拡張されたメソッドはエントリポイントと呼ばれます
。3通知(增强)
。:実際の拡張の論理部分は通知(拡張)と呼ばれます。 ;分割:フロント、リア、サラウンド、例外、最終通知;
4切面
。:アクション、エントリポイントに通知を適用するプロセスです
5.AOP操作
1. Springフレームワークは通常AspectJに基づいてAOP操作を実装します。AspectJはSpringのコンポーネントではありません。独立したAOPフレームワークです。通常、AspectJとSpringフレームワークはAOP操作のために組み合わされます
。2。に基づいてAOP操作を実装する2つの方法AspectJ
①xml設定ファイルに
基づく②アノテーション方式に基づく
3.プロジェクトエンジニアリングにAOP関連の依存関係を導入します
。4。エントリポイント式
(1)ポイントカット式関数:どのクラスのどのメソッドを拡張するかを知る
(2)構文構造:execution([权限修饰符] [返回类型] [类全路径] [方法名称 ]([参数列表]) )
例1:com.atguigu.dao.BookDaoクラスexecution(* com.atguigu.dao .BookDao.add( ...))
例2:com.atguigu.dao.BookDaoクラスのすべてのメソッドの実行を拡張します(* com.atguigu.dao.BookDao。*(...))
例3:com.atguiguのすべてのクラス.daoパッケージとクラス内のすべてのメソッドは拡張された実行です(* com.atguigu.dao ..(…))
1AspectJアノテーションに基づく操作
1️⃣クラスを作成し、クラス内のメソッドを定義します
public class User{
public void add(){
System. out .println("add.......");
}
}
2️⃣拡張クラスの作成(拡張ロジックの記述)
在增强类里面,创建方法,让不同方法代表不同通知类型
public class UserProxy {
public void before() {
// 前置通知
System. out .println("before......");
}
}
3️⃣通知構成を実行し、Spring構成ファイルで注釈スキャンを有効にします
<context:component-scan basepackage="com.atguigu.spring5.aopanno"></context:component-scan>
そして、アノテーションを使用してUserオブジェクトとUserProxyオブジェクトを作成します(つまり、着用@Component
したクラスにアノテーションを追加します)
4️⃣拡張クラスに別の@AspectJ
アノテーションを追加します
5️⃣最後に、Spring構成ファイルでプロキシオブジェクトの生成をオンにすることを忘れないでください
<! -- 开启 Aspect 生成代理对象 -- >
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
6️⃣、さまざまなタイプの通知を構成します。
拡張クラスで、通知タイプの注釈を通知メソッドとして追加し、エントリポイント式の構成を使用します。
// 增强的类
@Component
@Aspect // 生成代理对象
public class UserProxy {
// 前置通知
//@Before 注解表示作为前置通知
@Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void before() {
System. out .println("before.........");
}
// 后置通知(返回通知)
@AfterReturning(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void afterReturning() {
System. out .println("afterReturning.........");
}
// 最终通知
@After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void after() {
System. out .println("after.........");
}
// 异常通知
@AfterThrowing(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void afterThrowing() {
System. out .println("afterThrowing.........");
}
// 环绕通知
@Around(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System. out .println("环绕之前.........");
// 被增强的方法执行
proceedingJoinPoint.proceed();
System. out .println("环绕之后.........");
}
}
7️⃣、同じエントリポイントの抽出
// 相同切入点抽取
@Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void pointdemo() {
}
// 前置通知
//@Before 注解表示作为前置通知
@Before(value = "pointdemo()")
public void before() {
System. out .println("before.........");
}
8️⃣、同じメソッドで拡張する複数の拡張クラスがあり、拡張クラスの優先度を設定し、拡張クラス
の上にアノテーション@Order(数値型の値)を追加します。数値型の値が小さいほど、優先度が高くなります。
@Component
@Aspect
@Order(1)
public class PersonProxy
2.アノテーション開発を十分に活用する
構成クラスを作成します。xml構成ファイルを作成する必要はありません。
@Configuration
@ComponentScan(basePackages = {
"com.atguigu"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
3.AspectJ構成ファイルの操作
1.拡張クラスと拡張クラスの2つのクラス、作成メソッドを
作成します。2。スプリング構成ファイルに2つのクラスオブジェクトを作成します。
<! -- 创建对象 -- >
<bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean>
<bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
3.Spring構成ファイルでエントリポイントを構成します
<! -- 配置 aop 增强 -- >
<aop:config>
<! -- 切入点 -- >
<aop:pointcut id="p" expression="execution(*com.atguigu.spring5.aopxml.Book.buy(..))"/>
<! -- 配置切面 -- >
<aop:aspect ref="bookProxy">
<! -- 增强作用在具体的方法上 -- >
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>