2023-01-18 一、AOP前奏-代理模式 1、手動實現動態代理環境搭建 (1)基於介面實現動態代理:JDK動態代理 (2)基於繼承實現動態代理:Cglib、javassist動態代理 2、實現動態代理的步驟 (1)一個類:Proxy ①概述:Proxy代理類的基類(類似於Object) ②作用 ...
2023-01-18
一、AOP前奏-代理模式
1、手動實現動態代理環境搭建
(1)基於介面實現動態代理:JDK動態代理
(2)基於繼承實現動態代理:Cglib、javassist動態代理
2、實現動態代理的步驟
(1)一個類:Proxy
①概述:Proxy代理類的基類(類似於Object)
②作用:newProxyInstance():創建代理對象
(2)一個介面:InvocationHandler
①概述:實現“動態織入效果”的關鍵介面
②作用:invoke(),執行invoke()實現動態織入效果
3、手動實現動態代理關鍵步驟
註意:代理對象與實現類(目標對象)是“兄弟”關係,不能相互轉換
(1)創建類(為實現創建代理對象工具類)
(2)提供屬性(目標對象:實現類)
(3)提供方法(創建代理對象)
(4)提供有參構造器(避免目標為空)
4、實例代碼
(1)開啟組件
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 開啟組件掃描--> <context:component-scan base-package="com.hh"></context:component-scan> </beans>
(2)介面
public interface Calc { /** * 加法 * @param a * @param b * @return */ int add(int a,int b); /** * 解放 * @param a * @param b * @return */ int sub(int a,int b); /** * 乘法 * @param a * @param b * @return */ int mul(int a,int b); /** *除法 * @param a * @param b * @return */ int div(int a,int b); }
(3)實現類
@Component public class CalcImpl implements Calc { @Override public int add(int a, int b) { int result = a + b; return result; } @Override public int sub(int a, int b) { int result = a - b; return result; } @Override public int mul(int a, int b) { int result = a*b; return result; } @Override public int div(int a, int b) { int result = a/b; return result; } }
(4)日誌類
public class MyLogging { /** * 方法之前 */ public static void beforeMethod(String methodName,Object[] arg){ System.out.println("==>Calc中"+methodName+"方法(),參數:"+ Arrays.toString(arg)); } /** * 方法之後 */ public static void afterMethod(String methodName,Object rs){ System.out.println("==>Calc中"+methodName+"方法(),結果:"+rs); } }
(5)代理類
public class MyProxy { /** * 目標對象(目標客戶) */ private Object target; public MyProxy(Object target){ this.target = target; } /** * 獲取目標對象的代理對象 * @return */ public Object getProxyObject(){ Object proxyObj = null; /* ClassLoader loader:類載入器,目標對象類載入器 Class<?>[] interfaces,目標對象實現介面,目標對象實現所有介面 InvocationHandler h */ ClassLoader classLoader = target.getClass().getClassLoader(); Class<?>[] interfaces = target.getClass().getInterfaces(); //創建代理對象 proxyObj = Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() { //執行invoke()實現動態織入效果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //獲取方法名(目標對象) String methodName = method.getName(); //執行目標方法之前,添加日誌 MyLogging.beforeMethod(methodName,args); //觸發目標方法 Object rs = method.invoke(target, args); //執行目標方法之後,添加日誌 MyLogging.afterMethod(methodName,rs); return rs; } }); return proxyObj; } }
(6)測試類
@ContextConfiguration(locations = "classpath:applicationContext_beforeAop.xml") @RunWith(SpringJUnit4ClassRunner.class) public class TestBeforeAop { @Autowired private Calc calc; @Test public void testBeforeAop(){ int add = calc.add(1,2); System.out.println("add = " + add); } @Test public void testBeforeAop2(){ //目標對象 Calc calc = new CalcImpl(); //代理工具類 MyProxy myProxy = new MyProxy(calc); //獲取代理對象 Calc calcProxy = (Calc)myProxy.getProxyObject(); //測試 int add = calcProxy.add(1, 2); int div = calcProxy.div(2, 1); System.out.println("add = " + add); System.out.println("div = " + div); } }