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() {
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("事務開始");
//執行目標對象的方法
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相關的知識。