第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Spring AOP 的代理模式

1. 前言

大家好,我們學習了 AOP 的概念,理解了 AOP 的作用,明白了什么是 AOP 面向切面編程,目的是進行解耦,可以自由地對某個功能方法做增強,而它的設計模式就是代理模式。

那么本小節(jié)我們就學習 AOP 設計模式之代理模式,明白代理模式的含義,掌握代理模式的語法,同時明白它的應用場景。

2. 代理模式介紹

3.1 概念解釋

代理名詞解釋為:以被代理人名義,在授權范圍內(nèi)與第三方實施行為。而在軟件行業(yè)中代理模式是一種非常常用的設計模式,跟現(xiàn)實生活中的邏輯一致。

在開發(fā)中代理模式的表現(xiàn)為:我們創(chuàng)建帶有現(xiàn)有對象的代理對象,以便向外界提供功能接口。代理對象可以在客戶端和目標對象之間起到中介的作用。

中介什么作用? 可以為被代理對象執(zhí)行一些附帶的,增加的額外功能。

代理模式圖例:

圖片描述

圖例解釋

  • 數(shù)字 1 處表示發(fā)起請求的客戶端;
  • 數(shù)字 2 處表示需要調(diào)用的接口;
  • 數(shù)字 3 處表示真實接口的實現(xiàn)類,執(zhí)行的代碼邏輯在此;
  • 數(shù)字 4 處表示代理對象,同樣實現(xiàn)了接口,覆寫了需要執(zhí)行的代碼 Request 方法;
  • 數(shù)字 5 處是代理類中多余的代碼邏輯,對原有方法的增強;
  • 數(shù)字 6 處是代理類中的執(zhí)行的被代理類的原始邏輯。

3.2 代理模式分類

上面已經(jīng)解釋了代理模式的概念和原理,在開發(fā)中,實現(xiàn)代理模式可以分為兩種。

  • 靜態(tài)代理:若代理類在程序運行前就已經(jīng)存在,那么這種代理方式被成為靜態(tài)代理 ,這種情況下的代理類通常都是我們在 Java 代碼中定義的, 靜態(tài)代理中的代理類和委托類會實現(xiàn)同一接口;
  • 動態(tài)代理:代理類在程序運行時創(chuàng)建的代理方式被稱為動態(tài)代理。 也就是說,這種情況下,代理類并不是在 Java 代碼中定義的,而是在運行時根據(jù)我們在 Java 代碼中的 “指示” 動態(tài)生成的。

下面,我們就針對這兩種模式演示效果… 各位看官隨我來。

3. 代碼模式測試

3.1 靜態(tài)代理實現(xiàn)

1.userService 接口代碼

public interface UserService {

    public void saveUser();
}

2.userServiceImpl 實現(xiàn)類代碼

@Service
public class UserServiceImpl implements  UserService {

    public void saveUser() {

        System.out.println("執(zhí)行service中的保存邏輯");
    }
}

3.userServiceProxy 代理類代碼

public class UserServiceProxy implements  UserService {
	//被代理類實現(xiàn)接口
    private UserService userService;

    public UserServiceProxy(UserService userService) {
        this.userService = userService;
    }
	//覆寫的方法
    @Override
    public void saveUser() {
        System.out.println("原始功能執(zhí)行之前的邏輯代碼");
        userService.saveUser();;
        System.out.println("原始功能執(zhí)行之后的邏輯代碼");
    }
}

代碼解釋

userService 接口和 userServiceImpl 實現(xiàn)類代碼不做贅述,已經(jīng)用過多次。

重點關注于在 userServiceProxy 代理類代碼,其中屬性為被代理類的接口,目的是傳入進來被代理類實例,對它做功能增強。

下面的 saveUser 方法是代理類執(zhí)行的邏輯,在方法內(nèi)部有增強的代碼邏輯,也保留了原始實例的代碼功能。

4. 測試代碼

public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(SpringConfig.class);
    context.refresh();
    //獲取接口實例
    UserService service = context.getBean(UserService.class);
    //創(chuàng)建實例的代理
    UserServiceProxy proxy = new UserServiceProxy(service);
    //執(zhí)行方法
    proxy.saveUser();
}

5. 測試結果

圖片描述

可以看到,執(zhí)行結果中即包含了被代理對象的原始保存方法的邏輯,也有代理類中對原始方法的兩個增強代碼。

3.2 動態(tài)代理實現(xiàn)

1. 創(chuàng)建動態(tài)處理器

public class DynamicProxy implements InvocationHandler {


    private Object object;

    public DynamicProxy(final Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                  System.out.println("執(zhí)行前邏輯");
                    Object result = method.invoke(object, args);
                  System.out.println("執(zhí)行后邏輯");
                   return result;
    }
}

2. 測試類代碼

public class SpringTest {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(SpringConfig.class);
        context.refresh();
        //獲取接口實例
        UserService service = context.getBean(UserService.class);
        //動態(tài)創(chuàng)建實例的代理
        UserService proxy = (UserService)Proxy.newProxyInstance(UserService.class.getClassLoader(),
                            new Class[]{UserService.class}, new DynamicProxy(service));
        //proxy執(zhí)行方法
        proxy.saveUser();

    }
}

代碼解釋

Proxy.newProxyInstance 是 JDK 提供的一個用于動態(tài)創(chuàng)建代理實例的方法,JDK 1.7 的 API 有如下說明:

圖片描述

紅線框的內(nèi)部是簡易方式創(chuàng)建代理對象的方式,也就是我們示例中代碼的實現(xiàn)方式,參數(shù)解釋如下:

  • ClassLoader loader: 指定當前目標對象使用的類加載器,獲取加載器的方法是固定的
  • Class<?>[] interfaces: 指定目標對象實現(xiàn)的接口的類型,使用泛型方式確認類型
  • InvocationHandler: 指定動態(tài)處理器,執(zhí)行目標對象的方法時,會觸發(fā)事件處理器的方法

3. 測試結果

圖片描述

4. 小結

本小節(jié)學習了代理模式以及它的的實現(xiàn),那么要求大家掌握的內(nèi)容如下:

1. 實現(xiàn)要素

被代理類最少實現(xiàn)一個接口。

2. 實現(xiàn)步驟

  1. newProxyInstance 方法獲取代理類實例;
  2. 編寫代理實例方法;
  3. 添加代理實例方法內(nèi)邏輯;
  4. invoke 方法中調(diào)用委托類,也就是被代理類的方法。