springAop之動態代理之一jdk技術實現原理即代碼解讀

Aop

簡介:

Aop(Aspect Oriented Programming)面向切面編程,是OOP面向對象編程的一種補充將程序中交叉業務(事務,日誌)代碼提取出來,封裝成切面,由AOP容器在適當時機位置將封裝成的切面動態的織入到具體業務邏輯中。

AOP不是spring特有的。

應用場合:適用於具有橫切邏輯的場合,如事務管理,日誌記錄,性能檢測,異常通知,訪問控制等。

作用:

不改變原有代碼的基礎動態添加新的功能。

模塊化。

術語:

連接點(JoinPoint):程序執行的某個特定位置,如方法調用前,方法調用後,方法拋出異常時,方法調用前後等。

切入點(PointCut):定位位置找到需要切入的連接點,即切點。

增強Advice也稱爲通知: 在切點上執行的一段代碼用來實現某些功能。

目標對象 Target :將執行增強處理的目標類。

織入(Weaving) :將增強添加到目標類具體切入點的過程。

代理(Proxy) :一個類被織入增強後,會產生一個代理類。

切面 Aspect :切點和增強的組合。

引介 Introduction 也稱爲引入。

實現原理

代理模式:

概念:爲其他對象提供一種代理,以控制對這個對象的訪問,起到中介的作用,通過代理對象訪問目標對象,可以增強額外的操作,擴展目標對象的功能。

分類:

靜態代理:代理類是程序員創建或工具生成的,所謂靜態代理就是程序運行之前就已經存在代理類的字節碼文件。缺點:代理對象需要和目標對象實現相同的接口,如果接口增加方法,目標對象和代理對象都要維護。

動態代理:代理類是程序在運行期間由JVM根據反射等機制動態生成的,自動生成代理類和代理對象,所謂動態就是在程序運行之前不存在代理類的字節碼文件。

代理三要素:

一:實現目標類的接口。

二:初始化目標類的實例。

三:交叉業務,要執行的操作。

動態代理:

JDK技術:

proxy.newProxyInstance(

classloader 目標類的類加載器

interfaces 目標類得到接口列表

InvocationHandler 交叉業務邏輯

)

缺點:目標對象必須實現一個或多個接口,如果沒有實現接口,則無法使用JDK的動態代理,此時可以使用cglib技術
代碼
書寫UserService接口

package springaop01.service;


/**
 * package_name:springaop01.service
 *
 * author:徐亞遠 Date:2020/2/18 18:29
 * 項目名:springDemo01
 * Description:
 **/
public interface UserService {

    /**
     * @Author : 徐亞遠
     * @Date : 2020/2/18 20:34
     * @param username
     * @param password
     * @Description :
     */
    void login(String username, String password);
}

書寫UserService的實現類UserServiceImpl

package springaop01.service.impl;

import springaop01.service.UserService;

/**
 * package_name:springaop01.service.impl
 * Author:徐亞遠
 * Date:2020/2/18 18:29
 * 項目名:springDemo01
 * Desription:
 **/
public class UserServlceImpl implements UserService {


    /**
     * @param password
     * @param username
     * @Author : 徐亞遠
     * @Date : 2020/2/18 21:03
     * @Description :
     */

    @Override
    public void login(String username, String password) {
        System.out.println("loginUserServiceImpl登錄:" + username + "    " + password);
    }
}

書寫測試類使用jdk動態代理技術

package springaop01.controller;

import springaop01.service.UserService;
import springaop01.service.impl.UserServlceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * package_name:springaop01.controller
 * @author:徐亞遠
 * Date:2020/2/18 18:41
 * 項目名:springDemo01
 * Description:
 **/
public class UserController {
    public static void main(String[] args) {
        /** 動態代理*/
        UserService userService = (UserService) Proxy.newProxyInstance(
                //目標類的類加載器
                UserServlceImpl.class.getClassLoader(),
                //目標類的接口
                new Class[]{UserService.class},
                //交叉業務
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("打印日誌:" + method.getName() + " start at: [" + System.currentTimeMillis()
                                +"]"+"   "+"args:"+Arrays.toString(args));
                        Object object = method.invoke(new UserServlceImpl(), args);
                        return object;
                    }
                }
        );
        userService.login("admin", "admin");


    }
}

實現結果如圖:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章