1. 程式人生 > 其它 >441、排列硬幣(Arranging Coins)

441、排列硬幣(Arranging Coins)

技術標籤:spring框架設計模式java設計模式spring

1 代理模式的產生

  • 額外功能

    1. 軟體設計者的角度Service層不需要額外功能
    2. Service層的呼叫者則需要額外功能
    
    示例:
    1. 房東(軟體設計者)出租房子,只想實現核心功能而不去實現額外功能
    	核心功能:
    		1.出租房屋
    		2.收錢
    	額外功能:
    		1.打廣告
    		2.帶客戶看方
    2. 房客(軟體呼叫者)則需要這些額外功能。
    此時房東和房客就會產生矛盾,應景而生中介(proxy)。房東不想實現的額外功能中介來實現
    

2 設計模式

2.1 概念
通過代理類,為原始類(目標類)增加額外的功能
2.2 好處
利於原始類的維護
2.3 示例場景
事務、日誌、效能檢測
2.4 核心要素
1. 原始類
2. 原始類實現的介面(代理類必須和原始類的方法保持一致,所以需要實現共同的介面)
3. 額外功能

3 靜態代理

3.1 編碼實現

在這裡插入圖片描述

3.2 存在問題
1. 每一個原始類都需要與之對應的代理類的實現,靜態類檔案數量過多,不利於專案管理
2. 額外功能難以維護,需要去修改每一個代理類的額外功能實現

4 動態代理

4.1 spring的動態代理
4.1.1 依賴jar包
org.springframework:spring-aop:5.1.14.RELEASE
org.aspectj:aspectjrt:1.8.8
org.aspectj:aspectjewaver:1.8.3
4.1.2 實現額外功能
/**
 * @author wl
 * @version 1.0
 * @Description 實現MethodBeforeAdvice介面重寫before方法,實現原始方法之前的額外功能
 * @date 2021/1/20 19:36
 */
public class Before implements MethodBeforeAdvice {

    /**
     * @Description 需要把在原始方法執行之前執行的額外功能寫在before方法中
     * @Param [method, objects, o]
     * @return
     */
@Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("--- method before advice ----"); } }
4.1.3 原始類、共同介面
// 共同介面
public interface UserService {
    
    boolean login(String name, String password);
}

// 原始類
public class UserServiceImpl implements UserService {
    @Override
    public boolean login(String name, String password) {
        return true;
    }
}
4.1.4 定義切入點
切入點:額外功能加入的位置

<!-- spring的xml配置檔案中定義切入點-->
<aop:config>
    <!-- 給所有方法加入額外功能 -->
	<aop:pointcut id="ex" expression="execution(* *(..))"
</aop:config>
4.1.5 組裝
<!-- 將切入點和額外功能整合 -->
<aop:config>
    <!-- 給所有方法加入額外功能 -->
	<aop:pointcut id="ex" expression="execution(* *(..))"/>
    <!-- 指定額外功能和切入點的id -->
    <aop:advisor advice-ref="before" pointcut-ref="ex"/>
</aop:config>
4.1.6 呼叫
spring的工廠通過原始物件的id值獲得的是代理物件
    <bean name="userService" class="UserServiceImpl"></bean>
    所以 getBean("userService")獲得的是代理物件。
將獲取的代理物件進行儲存,可通過共同介面的型別宣告
	UserService userService = (UserSerivce)applicationContext.getBean("userService");
4.2 spring動態代理細節
4.2.1 代理類存放位置
Spring框架在執行時,通過動態位元組碼技術,在JVM中建立的,代理類執行在JVM內部。生命週期和JVM一致
4.2.2 動態位元組碼
不存在靜態java檔案,也就無法編譯成class檔案。
動態位元組碼是通過第三方的動態位元組碼框架在JVM中建立。如:Cglib、ASM、Javassist
有了位元組碼就可在JVM中建立物件
4.2.3 動態代理好處
1. 不需要定義代理類檔案,都是JVM執行過程中動態建立。不會造成類檔案過程,而影響專案管理的問題。
2. 在額外功能不改變的情況下,只需要指定原始類,不再需要如靜態代理般自己定義代理檔案
3. 額外功能要改變的化,只需要重新實現Advice介面重新組裝,不再需要如靜態代理般每個代理都去修改
1. 不需要定義代理類檔案,都是JVM執行過程中動態建立。不會造成類檔案過程,而影響專案管理的問題。
2. 在額外功能不改變的情況下,只需要指定原始類,不再需要如靜態代理般自己定義代理檔案
3. 額外功能要改變的化,只需要重新實現Advice介面重新組裝,不再需要如靜態代理般每個代理都去修改