IOC
Application的繼承關係
-
ApplicationContext的實現類
圖片來源於https://www.javadoop.com/post/spring-ioc -
ApplicationContext的父接口
圖片來源於https://www.javadoop.com/post/spring-ioc
容器的啓動過程
從AbstractApplicationContext抽象類的refresh方法開始。
- 準備工作
記錄下容器的啓動時間,標記容器開啓和關閉狀態位,校驗配置文件 - 解析配置文件,創建BeanDefinition實例,註冊進BeanFactory中
(1)將配置文件轉換成一顆DOM樹,從根節點開始解析文件。
(2)解析default namespace涉及到的四個標籤 < import/> < alias/> < bean/>和< beans/> ;
解析其他屬於custom下的標籤
(3)以< bean/>標籤爲例,根據標籤下的內容形成一個個的BeanDefiniton,然後放入註冊中心中,說到底核心是一個beanName->BeanDefinition的map - 設置BeanFactory的類加載器,添加BeanPostProcessor,手動註冊幾個bean
- 具體的子類添加一個特殊的BeanFactoryPostProcessor 的實現類或做點什麼事
- 調用上一步實現類的PostProcessorBeanFactory(factory)回調方法
- 註冊BeanPostProcessor實現類,其中的兩個方法會在Bean初始化之前和初始化之後得到執行
- 初始化當前ApplicationContext的MessageSource
- 初始化當前ApplicationContext的事件廣播器
- 註冊事件監聽器
- 初始化所有的非懶加載 singleton beans
(1)預初始化:如果有Bean繼承關係,合併父Bean的配置;如果bean實現了SmartInitializingSingleton 接口,進行相應的函數回調等等。
(2)正式初始化:判斷bean是否已被初始化,若被初始化則直接返回,否則就進行初始化。分爲三步:
第一步–創建Bean實例
如果不存在方法覆寫,就利用java反射實例化,否則使用CGLB
第二步–Bean屬性注入
通過名字裝配、通過類型裝配等
第三步–方法回調
- 如果bean實現了BeanNameAware、BeanClassLoaderAware或者BeanFactoryAware接口,調用回調方法
- 如果bean註冊了BeanPostProcessor實現類,則調用postProcessBeforeInitialization 方法
- 如果bean實現了initializingBean接口,調用afterProperties()方法
調用init-method配置的方法- 如果bean註冊了BeanPostProcessor實現類,則調用postProcessAfterInitialization 方法
- 廣播事件
AOP
Spring對AOP的支持
Spring提供了四種類型的AOP支持,分別爲:
- 基於代理的經典SpringAOP
- 純POJO切面
- @AspectJ註解驅動的切面
- 注入式AspectJ切面(適用於Spring的各個版本)
前三種都是SpringAOP實現的變體,SpringAOP構建在動態代理基礎上,因此Spring對AOP的支持侷限於方法攔截。
基於xml配置的AOP模式
以DefaultAdvisorAutoProxyCreator 爲例來進行追蹤,可以發現它是BeanPostProcessor接口的子類。IOC容器在初始化Bean的最後一步中會調用回調方法postProcessAfterInitialization ,該方法是BeanPostProcessor的接口方法。
對於BeanPostProcessor的實現類AbstractAutoProxyCreator,它是這樣實現postProcessAfterInitialization 方法的:
- 通過createProxy方法區創建ProxyFactory實例,ProxyFactory中包含了Advisor、targetSource等信息。其中的Advisor就是利用Pointcut正則表達式指定的範圍匹配得來的。
- 使用createAopProxy方法返回AOPProxy實例。如果被代理的目標類實現了接口,就使用jdk動態代理;沒有實現任何接口,會使用CGLIB實現代理;如果設置了proxy-target-class=“true”,那都會使用CGLIB。
當類的方法被private或者final修飾的時候,也不能夠使用jdk動態代理。 - 返回AopProxy實例後繼續調用getProxy(classLoder)方法,因爲AopProxy實例有jdk動態代理和CGLIB兩種代理方法,所以會用兩種不同的方式獲得代理對象。
基於註解驅動的AOP模式
Spring Aop中@Aspect的實現原理:
開啓@Aspect有兩種方式,一個是<aop:aspectj-autoproxy/>
,一個是@EnableAspectJAutoProxy
,它們的原理都是一樣的,通過註冊一個bean來實現。那這是一個怎樣的Bean?
以<aop:aspectj-autoproxy/>
爲例,解析這個標籤會用到AopNamespaceHandler->AspectJAutoProxyBeanDefinitionParser-> …-> 註冊了一個類名爲AnnotationAwareAspectJAutoProxyCreator的Bean,查看繼承關係,發現它也是BeanPostProcessor接口的一個實現類,所以後面同樣會在IOC容器初始化Bean實例的最後調用回調方法創建Bean的代理對象。