Spring筆記3

来源:https://www.cnblogs.com/train99999/archive/2019/07/19/11216186.html
-Advertisement-
Play Games

動態代理 特點:位元組碼隨用隨創建,隨用隨載入 作用:不修改源碼的基礎上對方法增強 分類: ​ 基於介面的動態代理 ​ 基於子類的動態代理 基於介面的動態代理: 涉及的類:Proxy 如何創建代理對象: ​ 使用Proxy類中的newProxyInstance方法 創建代理對象的要求:被代理的類最少實 ...


動態代理**

特點:位元組碼隨用隨創建,隨用隨載入

作用:不修改源碼的基礎上對方法增強

分類:

​ 基於介面的動態代理

​ 基於子類的動態代理

基於介面的動態代理:

涉及的類:Proxy

如何創建代理對象:

​ 使用Proxy類中的newProxyInstance方法

創建代理對象的要求:被代理的類最少實現一個介面,如果沒有則不能使用

newProxyInstance方法的參數:

ClassLoader :類載入器,他是用於載入代理對象位元組碼的,和被代理使用相同的類載入器

Class[] :位元組碼數組:他是用於讓代理對象和被代理對象有相同方法

InvocationHandler:用於提供增強的代碼,他是讓我們寫如何代理,一般都是些一個該介面的實現類,通常情況下都是匿名內部類

package com.itheima;


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

public class Client {
    public static void main(String[] args) {
        final Producer producer = new Producer();
        producer.saleProduct(10000f);

       Iproducer proxyProducer = (Iproducer)Proxy.newProxyInstance(producer.getClass().getClassLoader(),
                producer.getClass().getInterfaces(),
                new InvocationHandler() {
                    //該方法的作用,具有攔截功能
                    //執行被代理對象的任何介面方法都會經過該方法
                    //proxy:代理對象的引用
                    //Method:當前執行的方法
                    //args:當前執行方法所需的參數
                    //return:和被代理對象方法有相同的返回值
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //提供增強的代碼
                        Object returnValue = null;
                        //獲取方法執行的參數
                        Float money = (Float)args[0];
                        //判斷當前方法
                        if("saleProduct".equals(method.getName())){
                        returnValue =  method.invoke(producer,money*0.8f);
                    }
                    return returnValue;
                    }
                });
        proxyProducer.saleProduct(10000f);
    }
}

基於子類的動態代理

需要導入cglib包

涉及的類:Enhancer

如何創建代理對象:使用Enhancer類中的create方法

創建代理對象的要求:被代理類不能是最終類

create方法的參數

Class:位元組碼,用於指定被代理對象的位元組碼

Callback:用於提供增強的代碼,一般寫的都是該介面的子介面實現類,MethodInterceptor

package com.itheima.cglib;


import com.itheima.Iproducer;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

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

public class Client {
    public static void main(String[] args) {
        final Producer producer = new Producer();
        producer.saleProduct(10000f);


       Producer cglibProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {

            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                //提供增強的代碼
                Object returnValue = null;
                //獲取方法執行的參數
                Float money = (Float)objects[0];
                //判斷當前方法
                if("saleProduct".equals(method.getName())){
                    returnValue =  method.invoke(producer,money*0.8f);
                }
                return returnValue;
            }
        });
       cglibProducer.saleProduct(10000f);
    }
}

AOP:全稱是Aspect Oriented Programming 面向切麵編程

把我們程式重覆的代碼抽取出來,在需要執行的時候,使用動態代理的技術,在不修改源碼的基礎上,對我們的已有方法進行增強

AOP相關術語

Joinpoint(連接點):所謂連接點是值那些被攔截到的點,在spring中,這些點指的是方法,因為spring只支持方法類型的連接點

pointcut(切入點):所謂切入點是指我們要對哪些JoinPoint進行攔截的定義(被增強的方法才是切入點)

Advice(通知/增強):所謂的通過指的是攔截到Joinpoint之後所要做的事情就是通知,通知的類型:前置通知,後置通知,異常通知,最終通知,環繞通知

Target(目標對象):代理的目標對象

Weaving(織入):指的是把增強應用到目標對象來創建新的代理對象的過程

Proxy(代理):一個類被AOP織入增強後,就產生一個結果代理類

Aspect(切麵):是切入和通知的結合

spring基於XML的AOP

1.導入兩個坐標

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>
    <artifactId>day03_eesy_03springAOP</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
    </dependencies>
</project>

2.創建業務層和dao層

package com.itheima.service.impl;

import com.itheima.service.IAccountService;

//賬戶業務層實現類
public class AccountServiceImpl implements IAccountService {

    public void saveAccount() {
        System.out.println("執行了保存");
    }

    public void updateAccount(int i) {
        System.out.println("執行了更新");
    }

    public int deleteAccount() {
        System.out.println("執行了刪除");
        return 0;
    }
}

3.準備一個具有公共代碼的類

package com.itheima.utils;
//用於記錄日誌的工具類,他裡面提供了公共的代碼
public class Logger {
    //用於列印日誌:計劃讓其在切入點方法執行之前執行(切入點方法就是業務層方法)
    public void printLog(){
        System.out.println("Logger類中的方法開始記錄日誌了");
    }
}

目的:在執行業務層的方法之前,先執行printLog方法,通過spring配置的方式來完成,不使用動態代理

4.配置xml

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--配置spring的Ioc,把service對象配置進來-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>

    <!--spring中基於xml的AOP配置步驟
        1.把通知Bean也交給spring來管理
        2.使用aop:config標簽表名開始AOP的配置
        3.使用aop:aspect標簽表明配置切麵
                id屬性:是給切麵提供一個唯一標識
                ref屬性:是指定通知類bean的Id
        4.在aop:aspect標簽的內部使用對象標簽來配置通知的類型
            我們現在的示例是讓printLog方法在切入點方法執行之前執行,所以是前置通知
                    method屬性:用於指定Logger類中哪個方法是前置通知
                    pointcut屬性:用於指定切入點表達式,該表達式含義指的是對業務層中哪些方法增強
            切入點表達式的寫法:
                關鍵字:execution(表達式)
                    表達式:訪問修飾符  返回值 包名.包名.包名....類名.方法(參數列表)
    -->
    <!--配置Logger類-->
    <bean id="logger" class="com.itheima.utils.Logger"></bean>

    <!--配置AOP-->
    <aop:config>
        <!--配置切麵-->
        <aop:aspect id="logAdvice" ref="logger">
            <!--配置通知類型,並且建立通知方法和切入點方法的關聯-->
            <aop:before method="printLog" pointcut="execution(public void com.itheima.service.impl.AccountServiceImpl.saveAccount())"></aop:before>
        </aop:aspect>

    </aop:config>
</beans>

5.測試類

package com.ithei.test;

import com.itheima.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

//測試AOP的配置
public class AOPTest {
    public static void main(String[] args) {
        //1.獲取容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.獲取UI小
        IAccountService as = (IAccountService)ac.getBean("accountService");
        //3.執行方法
        as.saveAccount();
    }
}

控制台輸出:

Logger類中的方法開始記錄日誌了
執行了保存

切入點表達式: execution(* com.itheima.service.impl..(..))

四種通知的配置

<!--配置AOP-->
    <aop:config>
        <!--配置切麵-->
        <aop:aspect id="logAdvice" ref="logger">
            <!--配置通知類型,並且建立通知方法和切入點方法的關聯-->
            <!--前置通知-->
            <aop:before method="beforePrintLog" pointcut="execution(* com.itheima.service.impl.*.*(..))"></aop:before>
            <!--後置通知-->
            <aop:after-returning method="afterReturningPrintLog" pointcut="execution(* com.itheima.service.impl.*.*(..))"></aop:after-returning>
            <!--異常通知-->
            <aop:after-throwing method="afterThrowingPrintLog" pointcut="execution(* com.itheima.service.impl.*.*(..))"></aop:after-throwing>
            <!--最終通知-->
            <aop:after method="afterPrintLog" pointcut="execution(* com.itheima.service.impl.*.*(..))"></aop:after>
        </aop:aspect>
    </aop:config>

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 模式介紹 外觀模式相比較之下比較簡單,模式設計中定義是為子系統中的一組介面提供一個一致的界面,此模式定義了一個高層介面,這個介面是的這一子系統更加容易使用。 如果不理解呢,簡單些說就是外觀模式提供了為內部提供了同意的介面層,解耦了子系統和客戶端,這樣客戶端只需要知道外觀類存在即可,不需要知道具 ...
  • 第四章 分詞 下雨天留客天留我不留 本打算先介紹“簡單搜索”,對ES的搜索有一個直觀的感受。但在寫的過程中發現分詞無論如何都繞不過去。 查詢, 查詢都與分詞息息相關,索性先介紹分詞。 ES作為一個開源的搜索引擎,其核心自然在於搜索,而搜索不同於我們在MySQL中的 查詢語句,無論我們在百度搜索一個關 ...
  • [TOC] 一、分散式事務前奏 事務:事務是由一組操作構成的可靠的獨立的工作單元,事務具備ACID的特性,即原子性、一致性、隔離性和持久性。 本地事務:當事務由資源管理器本地管理時被稱作本地事務。本地事務的優點就是支持嚴格的ACID特性,高效,可靠,狀態可以只在資源管理器中維護,而且應用編程模型簡單 ...
  • 開篇:自己自學java拖拖拉拉的也有半年了,一學期里有很多事讓我停止學習java,轉眼間開學就要大四找工作了,想用一個暑假好好學習一些java,想掌握一門技術讓自己餓不死。本想每天寫一些筆記總結,發現那樣的話太費時間了,即便寫了,我自己都不看。最後,我決定還是以題的形式寫成文章,方便自己複習,同時也 ...
  • Sentinel API Github : "WIKI " Sphu (指明要保護的資源名稱) Tracer (指明調用來源,異常統計介面) ContextUtil(標示進入調用鏈入口) 流控規則(針對來源屬性) 降級規則 Sentinel Annotation 源碼: & 使用該註解重構上述方法 ...
  • 因為盤搜搜索出來的鏈接有很多已經失效了,影響找數據的效率,因此想到了用爬蟲來過濾出有效的鏈接,順便練練手~ 這是本次爬取的目標網址http://www.pansou.com,首先先搜索個python,之後打開開發者工具, 可以發現這個鏈接下的json數據就是我們要爬取的數據了,把多餘的參數去掉, 剩 ...
  • 1、多態介紹 面向對象三大特征:封裝、繼承、多態。多態是Java面向對象最核心,最難以理解的內容。從一定角度來看,封裝和繼承幾乎都是為多態而準備的。 多態就是指程式中定義的引用變數所指向的具體類型和通過該引用變數發出的方法調用在編譯時並不確定,而是在程式運行期間才確定,即一個引用變數倒底會指向哪個類 ...
  • Java中最基本的單位是類,Java中用class描述事物也是如此 成員變數 就是事物的屬性 成員方法 就是事物的行為 成員變數 就是事物的屬性 成員方法 就是事物的行為 定義類其實就是定義類的成員(成員變數和成員方法) a:成員變數 和以前定義變數是一樣的,只不過位置發生了改變。在類中,方法外。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...