大白話講解IOC和AOP

玄之不玄發表於2022-02-15

IOC和AOP

什麼是IOC

IoC(Inversion of control)控制反轉,它是一種思想,而Spring Framework實現了這一思想。Ioc也稱為依賴注入(DI)。

IOC控制反轉,即將new 物件的權利交給Spring容器。

將建立物件的控制權交給Spring容器有什麼好處呢?

想象這樣一個場景,我們要建立一個物件,這個物件可能依賴一個或多個其他物件,就像我們建立下面這個物件的樣子。

@Controller
public class TestService {
    @Autowired
    private TestOneDao testOneDao;
    @Autowired
    private TestTwoDao testTwoDao;
}

我們要知道,我們依賴的物件,也可能會依賴其他的物件。這是一個巢狀的過程。要是這些依賴關係都由我們來管理,想想都崩潰吧。所以索性讓Spring容器來管理這些依賴關係,也就是自動幫我們注入這些依賴。這樣子我們要使用某一個物件的時候,直接向IoC容器拿就可以了。

所以現在就比較好理解控制反轉

控制:指物件建立的權利

反轉:將控制權交給IOC容器

IoC容器和工廠模式有什麼關係呢?

IoC中最基本的技術就是“反射”程式設計,通俗的講就是根據給出的類名(字串形式)來動態地生成物件

我們可以把IoC容器看做是一個工廠,我們需要什麼物件,直接向工廠拿就行了,一般的工產模式只能生產某一類商品,但是IoC容器它能生產不同型別的商品,之所以能做到這一點,是因為它比一般工廠模式多使用了反射機制。

還記得我們剛學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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">  (1) (2)
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

這個全限定類名(class後面跟著的)就是反射生產物件所需的。

什麼是AOP?

AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期間動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數語言程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。(百度百科)

上面的不是很好理解,舉一個有關事務的例子。

大家學習Spring的時候,可能會接觸過程式設計式事務管理宣告式事務管理

程式設計式事務管理:簡單的理解就是自己編寫事務邏輯

宣告式事務管理:一個註解就搞定了,底層就是通過AOP實現的。

雖然宣告式事務管理是通過AOP來實現的,但是想要理解AOP的原理,還得從程式設計式事務管理開始。

虛擬碼如下(把我們的業務程式碼包裹在事務中)

事務開始
	業務程式碼
事務提交

真正程式碼

@Autowired
private TransactionTemplate transactionTemplate;
public void test() {

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {

                try {

                    // ....  業務程式碼
                } catch (Exception e){
                    //回滾
                    transactionStatus.setRollbackOnly();
                }

            }
        });
}

程式設計式事務管理存在什麼問題呢?

如果我們有另一個業務程式碼需要進行事務控制,那我們就需要重複編寫上面的事務邏輯程式碼。導致程式碼重複量大,於是人們提出了AOP面向切面程式設計。

AOP,在不改變我們原有程式碼的前提下,將程式碼加強(增加事務)。

那AOP是如何不改變原有程式碼,使得業務程式碼加強的呢?其實是基於代理模式。

如果不懂代理模式的可以看一下尚**的視訊,直達代理模式:https://www.bilibili.com/video/BV1G4411c7N4?p=94

下面進行模擬

目標:我們要增強Student的learn()方法(比如新增事務、日誌、安全等)

public class Student {
    public void learn(long ms) {
        System.out.println("student is learning!");
    }
}
public class ProxyFactory implements MethodInterceptor {
    //代理的物件
    private Object target;
	
    //我們要代理的物件是哪一個就傳進來哪一個(這裡傳進來的是Student)
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //這個方法看不懂也沒有關係,只需要知道它返回了一個代理物件(也就是target的代理物件,這裡是Student的代理物件)
    public Object getProxyInstance() {
        //1. 例項化工具類
        Enhancer en = new Enhancer();
        //2. 設定父類
        en.setSuperclass(this.target.getClass());
        //3. 設定回撥函式
        en.setCallback(this);
        //4. 建立子類,也就是代理物件
        return en.create();
    }

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("事務開始");
        long begin = System.currentTimeMillis();
        //執行目標物件的方法
        Object returnVal = method.invoke(target, objects);
        System.out.println("事務結束");
        return returnVal;
    }

}

public static void main() {
    ProxyFactory proxyFactory = new ProxyFactory(new Plane());
    Student student = (Student) proxyFactory.getProxyInstance();
    student.learn();
}

最終輸出

事務開始
student is learning!
事務結束

參考:

中文官網:https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/core.html

IoC實現原理:https://blog.csdn.net/fuzhongmin05/article/details/61614873

依賴注入:https://blog.csdn.net/xzp_12345/article/details/77885614
有幫助的話,動個小指點個贊吧,歡迎關注我的公眾號玩程式設計地碼農,目前在寫資料結構與演算法、計算機基礎、java相關的知識。

相關文章