1. 程式人生 > >AOP那點事兒:面向切面程式設計(1)

AOP那點事兒:面向切面程式設計(1)

今天我要和大家分享的是 AOP(Aspect-Oriented Programming)這個東西,名字與 OOP 僅差一個字母,其實它是對 OOP 程式設計方式的一種補充,並非是取而代之。翻譯過來就是“面向方面程式設計”,可我更傾向於翻譯為“面向切面程式設計”。它聽起有些的神祕,為什麼呢?當你看完這篇文章的時候,就會知道,我們做的很重要的工作就是去寫這個“切面” 。那麼什麼是“切面”呢?

沒錯!就是用一把刀來切一坨面。注意,相對於面而言,我們一定是橫著來切它,這簡稱為“橫切”。可以把一段程式碼想象成一坨面,同樣也可以用一把刀來橫切它,下面要做的就是如何去實現這把刀!

需要澄清的是,這個概念不是由 Rod Johnson(老羅)提出的。其實很早以前就有了,目前最知名最強大的 Java 開源專案就是 AspectJ 了,然而它的前身是 AspectWerkz(該專案已經在 2005 年停止更新),這才是 AOP 的老祖宗。老羅(一個頭發禿得和我老爸有一拼的天才)寫了一個叫做 Spring 框架,從此一炮走紅,成為了 Spring 之父。他在自己的 IOC 的基礎之上,又實現了一套 AOP 的框架,後來彷彿發現自己越來越走進深淵裡,在不能自拔的時候,有人建議他還是整合 AspectJ 吧,他在萬般無奈之下才接受了該建議。於是,我們現在用得最多的想必就是 Spring + AspectJ 這種 AOP 框架了。

那麼 AOP 到底是什麼?如何去使用它?本文將逐步帶您進入 AOP 的世界,讓您感受到前所未有的暢快!

不過在開始講解 AOP 之前,我想有必要回憶一下這段程式碼:

  1. 寫死程式碼

先來一個介面:

public interface Greeting {
    void sayHello(String name);
}

還有一個實現類:

public class GreetingImpl implements Greeting {

    @Override
    public void sayHello(String name) {
        before();
        System.out.println("Hello! "
+ name); after(); } private void before() { System.out.println("Before"); } private void after() { System.out.println("After"); } }

before() 與 after() 方法寫死在 sayHello() 方法體中了,這樣的程式碼的味道非常不好。如果哪位仁兄大量寫了這樣的程式碼,肯定要被你的架構師罵個夠嗆。

比如:我們要統計每個方法的執行時間,以對效能作出評估,那是不是要在每個方法的一頭一尾都做點手腳呢?

再比如:我們要寫一個 JDBC 程式,那是不是也要在方法的開頭去連線資料庫,方法的末尾去關閉資料庫連線呢?

這樣的程式碼只會把程式設計師累死,把架構師氣死!

一定要想辦法對上面的程式碼進行重構,首先給出三個解決方案:

  1. 靜態代理

最簡單的解決方案就是使用靜態代理模式了,我們單獨為 GreetingImpl 這個類寫一個代理類:

public class GreetingProxy implements Greeting {

    private GreetingImpl greetingImpl;

    public GreetingProxy(GreetingImpl greetingImpl) {
        this.greetingImpl = greetingImpl;
    }

    @Override
    public void sayHello(String name) {
        before();
        greetingImpl.sayHello(name);
        after();
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}

就用這個 GreetingProxy 去代理 GreetingImpl,下面看看客戶端如何來呼叫:

public class Client {

    public static void main(String[] args) {
        Greeting greetingProxy = new GreetingProxy(new GreetingImpl());
        greetingProxy.sayHello("Jack");
    }
}

這樣寫沒錯,但是有個問題,XxxProxy 這樣的類會越來越多,如何才能將這些代理類儘可能減少呢?最好只有一個代理類。

這時我們就需要使用 JDK 提供的動態代理了。

  1. JDK 動態代理
public class JDKDynamicProxy implements InvocationHandler {

    private Object target;

    public JDKDynamicProxy(Object target) {
        this.target = target;
    }

    @SuppressWarnings("unchecked")
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}

客戶端是這樣呼叫的:

public class Client {

    public static void main(String[] args) {
        Greeting greeting = new JDKDynamicProxy(new GreetingImpl()).getProxy();
        greeting.sayHello("Jack");
    }
}

這樣所有的代理類都合併到動態代理類中了,但這樣做仍然存在一個問題:JDK 給我們提供的動態代理只能代理介面,而不能代理沒有介面的類。有什麼方法可以解決呢?

  1. CGLib 動態代理

我們使用開源的 CGLib 類庫可以代理沒有介面的類,這樣就彌補了 JDK 的不足。CGLib 動態代理類是這樣玩的:

public class CGLibDynamicProxy implements MethodInterceptor {

    private static CGLibDynamicProxy instance = new CGLibDynamicProxy();

    private CGLibDynamicProxy() {
    }

    public static CGLibDynamicProxy getInstance() {
        return instance;
    }

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> cls) {
        return (T) Enhancer.create(cls, this);
    }

    @Override
    public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        before();
        Object result = proxy.invokeSuper(target, args);
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}

以上程式碼中了 Singleton 模式,那麼客戶端呼叫也更加輕鬆了:

public class Client {

    public static void main(String[] args) {
        Greeting greeting = CGLibDynamicProxy.getInstance().getProxy(GreetingImpl.class);
        greeting.sayHello("Jack");
    }
}

到此為止,我們能做的都做了,問題似乎全部都解決了。但事情總不會那麼完美,而我們一定要追求完美!

老羅搞出了一個 AOP 框架,能否做到完美而優雅呢?請大家繼續往下看吧!

  1. Spring AOP:前置增強、後置增強、環繞增強(程式設計式)

在 Spring AOP 的世界裡,與 AOP 相關的術語實在太多,往往也是我們的“攔路虎”,不管是看那本書或是技術文件,在開頭都要將這些術語逐個灌輸給讀者。我想這完全是在嚇唬人了,其實沒那麼複雜的,大家放輕鬆一點。

我們上面例子中提到的 before() 方法,在 Spring AOP 裡就叫 Before Advice(前置增強)。有些人將 Advice 直譯為“通知”,我想這是不太合適的,因為它根本就沒有“通知”的含義,而是對原有程式碼功能的一種“增強”。再說,CGLib 中也有一個 Enhancer 類,它就是一個增強類。

此外,像 after() 這樣的方法就叫 After Advice(後置增強),因為它放在後面來增強程式碼的功能。

如果能把 before() 與 after() 合併在一起,那就叫 Around Advice(環繞增強),就像漢堡一樣,中間夾一根火腿。

這三個概念是不是輕鬆地理解了呢?如果是,那就繼續吧!

我們下面要做的就是去實現這些所謂的“增強類”,讓他們橫切到程式碼中,而不是將這些寫死在程式碼中。

先來一個前置增強類吧:

public class GreetingBeforeAdvice implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Before");
    }
}

注意:這個類實現了 org.springframework.aop.MethodBeforeAdvice 介面,我們將需要增強的程式碼放入其中。

再來一個後置增強類吧:

public class GreetingAfterAdvice implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("After");
    }
}

類似地,這個類實現了 org.springframework.aop.AfterReturningAdvice 介面。

最後用一個客戶端來把它們整合起來,看看如何呼叫吧:

public class Client {

    public static void main(String[] args) {
        ProxyFactory proxyFactory = new ProxyFactory();     // 建立代理工廠
        proxyFactory.setTarget(new GreetingImpl());         // 射入目標類物件
        proxyFactory.addAdvice(new GreetingBeforeAdvice()); // 新增前置增強
        proxyFactory.addAdvice(new GreetingAfterAdvice());  // 新增後置增強 

        Greeting greeting = (Greeting) proxyFactory.getProxy(); // 從代理工廠中獲取代理
        greeting.sayHello("Jack");                              // 呼叫代理的方法
    }
}

請仔細閱讀以上程式碼及其註釋,您會發現,其實 Spring AOP 還是挺簡單的,對嗎?

當然,我們完全可以只定義一個增強類,讓它同時實現 MethodBeforeAdvice 與 AfterReturningAdvice 這兩個介面,如下:

public class GreetingBeforeAndAfterAdvice implements MethodBeforeAdvice, AfterReturningAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Before");
    }

    @Override
    public void afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("After");
    }
}

這樣我們只需要使用一行程式碼,同時就可以新增前置與後置增強:

proxyFactory.addAdvice(new GreetingBeforeAndAfterAdvice());

剛才有提到“環繞增強”,其實這個東西可以把“前置增強”與“後置增強”的功能給合併起來,無需讓我們同時實現以上兩個介面。

public class GreetingAroundAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        before();
        Object result = invocation.proceed();
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}

環繞增強類需要實現 org.aopalliance.intercept.MethodInterceptor 介面。注意,這個介面不是 Spring 提供的,它是 AOP 聯盟(一個很牛逼的聯盟)寫的,Spring 只是借用了它。

在客戶端中同樣也需要將該增強類的物件新增到代理工廠中:

proxyFactory.addAdvice(new GreetingAroundAdvice());

好了,這就是 Spring AOP 的基本用法,但這只是“程式設計式”而已。Spring AOP 如果只是這樣,那就太傻逼了,它曾經也是一度宣傳用 Spring 配置檔案的方式來定義 Bean 物件,把程式碼中的 new 操作全部解脫出來。

  1. Spring AOP:前置增強、後置增強、環繞增強(宣告式)

先看 Spring 配置檔案是如何寫的吧:

<?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
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 掃描指定包(將 @Component 註解的類自動定義為 Spring Bean) -->
    <context:component-scan base-package="aop.demo"/>

    <!-- 配置一個代理 -->
    <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="interfaces" value="aop.Greeting"/> <!-- 需要代理的介面 -->
        <property name="target" ref="greetingImpl"/>       <!-- 介面實現類 -->
        <property name="interceptorNames">                 <!-- 攔截器名稱(也就是增強類名稱,Spring Bean 的 id) -->
            <list>
                <value>greetingAroundAdvice</value>
            </list>
        </property>
    </bean>

</beans>

一定要閱讀以上程式碼的註釋,其實使用 ProxyFactoryBean 就可以取代前面的 ProxyFactory,其實它們倆就一回事兒。我認為 interceptorNames 應該改名為 adviceNames 或許會更容易讓人理解,不就是往這個屬性裡面新增增強類嗎?

此外,如果只有一個增強類,可以使用以下方法來簡化:

<bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="interfaces" value="aop.Greeting"/>
        <property name="target" ref="greetingImpl"/>
        <property name="interceptorNames" value="greetingAroundAdvice"/> <!-- 注意這行配置 -->
</bean>

還需要注意的是,這裡使用了 Spring 2.5+ 的特性“Bean 掃描”,這樣我們就無需在 Spring 配置檔案裡不斷地定義 了,從而解脫了我們的雙手。

看看這是有多麼的簡單:

@Component
public class GreetingImpl implements Greeting {

    ...
}

@Component
public class GreetingAroundAdvice implements MethodInterceptor {

    ...
}

最後看看客戶端吧:

public class Client {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml"); // 獲取 Spring Context
        Greeting greeting = (Greeting) context.getBean("greetingProxy");                        // 從 Context 中根據 id 獲取 Bean 物件(其實就是一個代理)
        greeting.sayHello("Jack");                                                              // 呼叫代理的方法
    }
}

程式碼量確實少了,我們將配置性的程式碼放入配置檔案,這樣也有助於後期維護。更重要的是,程式碼只關注於業務邏輯,而將配置放入檔案中。這是一條最佳實踐!

除了上面提到的那三類增強以外,其實還有兩類增強也需要了解一下,關鍵的時候您要能想得到它們才行。

  1. Spring AOP:丟擲增強

程式報錯,丟擲異常了,一般的做法是列印到控制檯或日誌檔案中,這樣很多地方都得去處理,有沒有一個一勞永逸的方法呢?那就是 Throws Advice(丟擲增強),它確實很強,不信你就繼續往下看:

@Component
public class GreetingImpl implements Greeting {

    @Override
    public void sayHello(String name) {
        System.out.println("Hello! " + name);

        throw new RuntimeException("Error"); // 故意丟擲一個異常,看看異常資訊能否被攔截到
    }
}

下面是丟擲增強類的程式碼:

@Component
public class GreetingThrowAdvice implements ThrowsAdvice {

    public void afterThrowing(Method method, Object[] args, Object target, Exception e) {
        System.out.println("---------- Throw Exception ----------");
        System.out.println("Target Class: " + target.getClass().getName());
        System.out.println("Method Name: " + method.getName());
        System.out.println("Exception Message: " + e.getMessage());
        System.out.println("-------------------------------------");
    }
}

丟擲增強類需要實現 org.springframework.aop.ThrowsAdvice 介面,在介面方法中可獲取方法、引數、目標物件、異常物件等資訊。我們可以把這些資訊統一寫入到日誌中,當然也可以持久化到資料庫中。

這個功能確實太棒了!但還有一個更厲害的增強。如果某個類實現了 A 介面,但沒有實現 B 介面,那麼該類可以呼叫 B 介面的方法嗎?如果您沒有看到下面的內容,一定不敢相信原來這是可行的!

  1. Spring AOP:引入增強

以上提到的都是對方法的增強,那能否對類進行增強呢?用 AOP 的行話來講,對方法的增強叫做 Weaving(織入),而對類的增強叫做 Introduction(引入)。而 Introduction Advice(引入增強)就是對類的功能增強,它也是 Spring AOP 提供的最後一種增強。建議您一開始千萬不要去看《Spring Reference》,否則您一定會後悔的。因為當您看了以下的程式碼示例後,一定會徹底明白什麼才是引入增強。

定義了一個新介面 Apology(道歉):

public interface Apology {
    void saySorry(String name);
}

但我不想在程式碼中讓 GreetingImpl 直接去實現這個介面,我想在程式執行的時候動態地實現它。因為假如我實現了這個介面,那麼我就一定要改寫 GreetingImpl 這個類,關鍵是我不想改它,或許在真實場景中,這個類有1萬行程式碼,我實在是不敢動了。於是,我需要藉助 Spring 的引入增強。這個有點意思了!

@Component
public class GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        return super.invoke(invocation);
    }

    @Override
    public void saySorry(String name) {
        System.out.println("Sorry! " + name);
    }
}

以上定義了一個引入增強類,擴充套件了 org.springframework.aop.support.DelegatingIntroductionInterceptor 類,同時也實現了新定義的 Apology 介面。在類中首先覆蓋了父類的 invoke() 方法,然後實現了 Apology 介面的方法。我就是想用這個增強類去豐富 GreetingImpl 類的功能,那麼這個 GreetingImpl 類無需直接實現 Apology 介面,就可以在程式執行的時候呼叫 Apology 介面的方法了。這簡直是太神奇的!

看看是如何配置的吧:

<?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
       http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="aop.demo"/>

    <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="interfaces" value="aop.demo.Apology"/>          <!-- 需要動態實現的介面 -->
        <property name="target" ref="greetingImpl"/>                    <!-- 目標類 -->
        <property name="interceptorNames" value="greetingIntroAdvice"/> <!-- 引入增強 -->
        <property name="proxyTargetClass" value="true"/>                <!-- 代理目標類(預設為 false,代理介面) -->
    </bean>
</beans>

需要注意 proxyTargetClass 屬性,它表明是否代理目標類,預設為 false,也就是代理介面了,此時 Spring 就用 JDK 動態代理。如果為 true,那麼 Spring 就用 CGLib 動態代理。這簡直就是太方便了!Spring 封裝了這一切,讓程式設計師不在關心那麼多的細節。我們要向老羅同志致敬,您是我們心中永遠的 idol!

當您看完下面的客戶端程式碼,一定會完全明白以上的這一切:

public class Client {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml");
        GreetingImpl greetingImpl = (GreetingImpl) context.getBean("greetingProxy"); // 注意:轉型為目標類,而並非它的 Greeting 介面
        greetingImpl.sayHello("Jack");

        Apology apology = (Apology) greetingImpl; // 將目標類強制向上轉型為 Apology 介面(這是引入增強給我們帶來的特性,也就是“介面動態實現”功能)
        apology.saySorry("Jack");
    }
}

沒想到 saySorry() 方法原來是可以被 greetingImpl 物件來直接呼叫的,只需將其強制轉換為該介面即可。

我們再次感謝 Spring AOP,感謝老羅給我們提供了這麼強大的特性!

其實,Spring AOP 還有很多精彩的地方,下一篇將介紹更多更有價值的 AOP 技術,讓大家得到更多的收穫。

未完,待續…

相關推薦

AOP事兒面向切面程式設計(1)

今天我要和大家分享的是 AOP(Aspect-Oriented Programming)這個東西,名字與 OOP 僅差一個字母,其實它是對 OOP 程式設計方式的一種補充,並非是取而代之。翻譯過來就是“面向方面程式設計”,可我更傾向於翻譯為“面向切面程式設計”。

spring面試題(四)面向切面程式設計AOP+MVC

Spring面向切面程式設計(AOP) 1.  解釋AOP 面向切面的程式設計,或AOP, 是一種程式設計技術,允許程式模組化橫向切割關注點,或橫切典型的責任劃分,如日誌和事務管理。   2. Aspect 切面 AOP

面試題 面向切面程式設計AOP)的理解

AOP是什麼?     AOP的全稱是Aspect Orient Programming,即面向切面程式設計。是對OOP(Object Orient Programming)的一種補充,戰門用於處理一些具有橫切性質的服務。常常用於日誌輸出、安全控制等。

Spring實踐面向切面程式設計AOP

原文連結:http://blog.csdn.net/zjf280441589/article/details/50816802 AOP引介 AOP(Aspect Oriented Programing)面向切面程式設計採用橫向抽取機制,以取代傳統的縱向繼承體系的重複

Spring aop 攔截器(即面向切面程式設計

package com.saic.grape; public interface UserService {     public void printUser(String user); } package com.saic.grape; public class Us

第二天 AOP 面向切面程式設計 、 JdbcTemplete 工具類使用

AOP 面向切面程式設計 、 JdbcTemplete 工具類使用 目錄 一、 什麼是 AOP ***** 二、 AOP 的底層實現 1、 JDK動態代理 2、 使用CGlib 完成動態代理 三、 Spring AOP 1、 傳統Spring AOP 提供

從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析簡單日誌記錄 + 服務切面快取

  今天的講解就到了這裡了,通過這兩個小栗子,大家應該能對面向切面程式設計有一些朦朧的感覺了吧

core學習歷程五 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析簡單日誌記錄 + 服務切面快取 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十一 || AOP自定義篩選,Redis入門 11.1

繼續學習 “老張的哲學”博主的系列教程,感謝大神們的無私分享 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析:簡單日誌記錄 + 服務切面快取 說是朦朧,,emmm,對我來說是迷糊哈。上半段正常,下半段有點難理解,操作是沒問題。多看幾遍再消

面向切面程式設計(3)AOP實現機制

1 AOP各種的實現   AOP就是面向切面程式設計,我們可以從幾個層面來實現AOP,如下圖。 圖1 AOP實現的不同層面   在編譯器修改原始碼,在執行期位元組碼載入前修改位元組碼或位元組碼載入後動態建立代理類的位元組碼,以下是各種實現機制的比較。  類別

Kotlin的Spring之旅(二)AOP面向切面程式設計

AOP(面向切面程式設計) AOP是OOP(面向物件程式設計)的延續,但是它和麵向物件的縱向程式設計不同,它是一個橫向的切面式的程式設計。可以理解為oop就是一根柱子,如果需要就繼續往上加長,而aop則是在需要的地方把柱子切開,在中間加上一層,再把柱子完美

iOS資料埋統計方案(附Demo): 執行時Method Swizzling機制與AOP程式設計(面向切面程式設計)...

#import "UIViewController+Trace.h"#import "TraceHandler.h"#import <objc/runtime.h>#import <objc/objc.h>#import "Aspects.h"@implementation UIVie

Spring Boot2(六)使用Spring Boot整合AOP面向切面程式設計

一、前言 眾所周知,spring最核心的兩個功能是aop和ioc,即面向切面和控制反轉。本文會講一講SpringBoot如何使用AOP實現面向切面的過程原理。 二、何為aop ​ aop全稱Aspect Oriented Programming,面向切面,AOP主要實現的目的是針對業務處理過程中的切面進行提取

《開源框架事兒19》特斯拉建“樁”與開源的生命力

充電站 otto 期權 eas gb2 平臺 程序 蘋果 名詞 在美國的矽谷,在中國的中關村,很多的技術先驅者懷揣夢想。用激情不懈地追求著他們宏遠的目標和巨大的個人財富。開源。正在成為這個時代眼下最火熱的名詞之中的一個。開源精神,作為一種合作協同的驅動力,正在發展為一種更

《開源框架事兒25》對框架模板引擎實現方式的改造實錄

port 內嵌 代碼調試 iter put 文件路徑 children nts fault 點滴悟透設計思想,Tiny模板引擎優化實錄! 增加框架設計興趣小組:http://bbs.tinygroup.org/group-113-1.html Tiny模板引擎的實

面向切面編程AOP的理解

glib 之間 切入點 targe con rgs 強制 sof 作用 AOP AOP(Aspect Oriented Programming),即面向切面編程,可以說是OOP(Object Oriented Programming,面向對象編程)的補充和完善。OOP引入

Map大家族的事兒(2)AbstractMap

bstr ans == new 實現 狀態 返回 說過 後者 AbstractMap是一個抽象類,它是Map接口的一個骨架實現,最小化實現了此接口提供的抽象函數。在Java的Collection框架中基本都遵循了這一規定,骨架實現在接口與實現類之間構建了一層抽象,其目的是

【小家java】POP(面向過程程式設計)、OOP(面向物件程式設計)、AOP面向切面程式設計)三種程式設計思想的區別和聯絡

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

3.AOP面向切面程式設計

1. 首先我要控制事務,要想控制事務就得使用一個connection 所以只能提取出來connection 所以注重物件的注入 這個重點就是怎麼注入的問題? 重點:加強聯絡 IOC 2. 1.怎麼踢掉重複程式碼? 2.動態代理!AOP 作用就是在

Spring Boot實戰系列(3)AOP面向切面程式設計

AOP是一種與語言無關的程式思想、程式設計正規化。專案業務邏輯中,將通用的模組以水平切割的方式進行分離統一處理,常用於日誌、許可權控制、異常處理等業務中。 快速導航 引入AOP依賴 AOP常用註解解析 實現日誌分割功能 @Pointcut 新增切入點 @Be

02 Spring的AOP面向切面程式設計

1、關於AOP AOP(Aspect Oriented Programming),即面向切面程式設計,可以說是OOP(Object Oriented Programming,面向物件程式設計)的補充和完善。OOP引入封裝、繼承、多型等概念來建立一種物件層次結構,用於模擬公共行為的一個集合。O