Java spring AOP面向切面程式設計JDK動态代理示例
- Java spring AOP(面向切面程式設計) JDK動态代理示例
-
- 目标類
-
- 目标類接口
- 目标類實作
- 切面類
- spring工廠
- 測試
Java spring AOP(面向切面程式設計) JDK動态代理示例
本文引用B站老師(“一個體面的人”釋出的視訊) spring架構教程相關内容,适合初學者了解使用
了解更多内容點選連結.
AOP概念:
(百度百科)
AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和運作期動态代理實作程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring架構中的一個重要内容,是函數式程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,進而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
JDK動态代理,可簡單的了解為将advice(增強)和到target(目标類)織入代理中,在每次執行目标類方法時,都會動态的執行對應的增強方法。在本示例中,即将切面類的before方法和after方法,通過spring工廠中的代理proxService,加到每個目标方法前、後執行。
目标類
目标類接口
檔案名:UserService.java
package com.itheima.a_proxy.a_jdk;
/*目标類接口*/
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
目标類實作
檔案名:UserServiceImpl.java
package com.itheima.a_proxy.a_jdk;
/*目标類實作*/
public class UserServiceImpl implements UserService {
@Override
public void addUser(){
System.out.println("a_proxy.a_jdk addUser");
}
@Override
public void updateUser(){
System.out.println("a_proxy.a_jdk updateUser");
}
@Override
public void deleteUser(){
System.out.println("a_proxy.a_jdk deleteUser");
}
}
切面類
切面類含有before方法和after方法
檔案名:MyAspect.java
package com.itheima.a_proxy.a_jdk;
/*切面類*/
public class MyAspect {
public void before(){
System.out.println("前方法");
}
public void after(){
System.out.println("後方法");
}
}
spring工廠
檔案名:MyBeanFactory.java
package com.itheima.a_proxy.a_jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyBeanFactory {
public static UserService createService(){
//return new UserServiceImpl();
//1.目标類,匿名類前加final
final UserService userService = new UserServiceImpl();
//2.切面類
final MyAspect myAspect = new MyAspect();
/*3.代理類:将目标類(切入點)和切面類(通知)結合,即切面
*Proxy.newProxyInstance(loader,interfaces,h)
* 參數1:loader,類加載器,動态代理類運作時建立,任何類都需要類加載器将其加載到記憶體。
* 一般情況:目前類.class.getClassLoader();
* 目标類執行個體.getClass.get...
* 參數2:interfaces,代理類需要實作的所有接口
* 方式1:目标類執行個體.getClass().getInterfaces();注意,隻能獲得自己的接口,不能獲得父類元素的接口
* 方式2:new Class[]{UserService.class} 例如:jsbc驅動 DriverManager 獲得接口Connection
* 參數3:InvocationHandler 處理類,接口,必須進行實作類,一般采用匿名内部
* 提供invoke(Object proxy, Method method, Object[] args)方法:代理類的每一個方法執行時,都将調用一次invoke
* 參數(1)Object proxy:代理對象
* 參數(2)Method method:代理對象目前執行的方法的描述對象(反射)
* 執行方法名獲得:method.getName()
* 執行方法:method.invoke(對象,實際參數)
* 參數(3)Object[] args:方法實際參數
* */
UserService proxService = (UserService) Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(),
userService.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//将目标類和切面類結合
//前執行
myAspect.before();
//執行目标方法
Object obj = method.invoke(userService,args);
//後執行
myAspect.after();
return obj;
}
});
return proxService;
}
}
測試
檔案名:TestJDK.java
package com.itheima.a_proxy.a_jdk;
import org.junit.Test;
import org.springframework.test.context.TestExecutionListeners;
public class TestJDK {
@Test
public void demo01(){
UserService userService = MyBeanFactory.createService();
userService.addUser();
userService.updateUser();
userService.deleteUser();
}
}
測試執行結果