《精通Spring4.x 企業應用開發實戰》讀書筆記java
1、概念web
IOC:spring
- 假設B類調用了A類,那麼A類的對象的建立是由B類來實現;
- IOC是指將A對象的建立由容器來完成,而且將建立好的對象注入到B類中供B類對象使用
好處:緩存
2、Resource接口tomcat
- 「classpath:」:只會在第一個加載的com.xxx包的類路徑下查找;
- 「classpath*:」:會掃描全部類路徑下的com.xxx包中的查找
3、Bean工廠springboot
- BeanFactory:
- 容器啓動時,將配置文件中的Bean裝載到容器(hashMap<beanName, BeanDefinition>)
- 配置文件中的Bean的初始化是在第一次調用時進行 - 「懶實例化」
- 緩存單例Bean,第二次調用時獲取bean從IOC容器緩存中獲取(hashMap<beanName, Bean>)
- ApplicationContext:在BeanFactory的基礎上,增長了「國際化支持」和「事件體系」
- 事件體系:
- ApplicationEventPublisher:發佈事件,實際上會調用ApplicationEventMulticaster實例來發布。
- ApplicationEventMulticaster:提供了監聽器註冊表,保存全部的監聽器;發佈事件,並通知相應的監聽器進行相應操做
- 上下文初始化時,建立全部單例Bean - 「急切實例化」
4、Spring啓動流程app
一、初始化BeanFactorypost
- 建立BeanFactory實例
- 將配置文件的信息裝入BeanDefinitionRegistry(Bean定義註冊表)中
- 使用ResourceLoader將配置文件裝載爲Resource對象
- 使用BeanDefinitionReader解析配置信息:將每個<bean>解析爲一個BeanDefinition對象,而後存儲到BeanDefinitionRegistry中
二、調用BeanFactoryPostProcessor性能
- 根據反射機制從BeanDefinitionRegistry中找出全部實現了BeanFactoryPostProcessor接口的Bean,並調用其postProcessBeanFactory()接口方法,實際上完成的工做主要是:- 可定製點
- 對使用佔位符的<bean>進行解析,獲得最終的配置值,即將半成品的BeanDefinition轉化爲徹底體的BeanDefinition對象
- 根據反射機制從BeanDefinitionRegistry中找出全部實現了java.beans.PropertyEditor接口的Bean,並自動將他們註冊到ProperEditorRegistry中
三、註冊BeanPostProcessorspa
- 根據反射機制從BeanDefinitionRegistry中找出全部實現了BeanPostProcessor接口的Bean,並將他們註冊到BeanPostProcessor的註冊表中 - 可定製點
- 重要點:Aop、動態代理都是基於這個實現的
四、初始化國際化信息資源
五、初始化應用上下文事件廣播器 - 事件
六、初始化特殊的Bean:鉤子方法 - 可定製點
- springboot在這一步建立了TomcatEmbeddedServletContainer,即內嵌的tomcat容器
七、註冊事件監聽器到ApplicationEventMulticaster的監聽器註冊表中
八、初始化全部的單例Bean,使用懶加載的除外;初始化Bean後,放入spring容器的緩衝池(hashMap<beanName, Bean>)
- 取出BeanDefinitionRegistry中的BeanDefinition對象,使用InstantiationStrategy實例化Bean;
- 使用BeanWrapper結合Bean實例和ProperEditorRegistry對Bean進行屬性注入操做;
- 使用3中註冊好的BeanPostProcessor對已經完成屬性設置的Bean進行後續加工,裝配置出準備就緒的Bean。
- 初始化 - init-method
- 放入緩衝池(單例),多例交給調用者(後續該Bean的生命週期由垃圾回收來定了)
九、發佈上下文刷新事件 :建立上下文刷新事件,事件廣播器負責將這些事件廣播到每一個註冊的事件監聽器中 - 事件
類比:springboot啓動核心流程
一、建立SpringApplication對象
- 判斷是不是web環境
- 建立並初始化ApplicationInitializer列表
- 建立並初始化ApplicationListener列表
- 初始化主類mainApplicationClass
二、執行run方法
- 獲取SpringApplicationRunListeners
- 建立了EventPublishingRunListener實例
- 建立事件廣播器
SimpleApplicationEventMulticaster實例
- 將以前初始化好的ApplicationListener列表所有註冊到事件廣播器的事件註冊表中
- 建立並初始化ConfigurableEnvironment
- 建立一個MutablePropertySources複合屬性源
- 構造包含server.port等啓動參數的屬性源,並設置到複合屬性源的首部,優先級最高
- 讀取application.properties文件內容,並構造爲一個name爲「applicationConfigurationProperties」的屬性源,並設置到複合屬性源的尾部
- 建立ConfigurableApplicationContext
- 準備ConfigurableApplicationContext
- 執行初始化好了的ApplicationInitializer列表
- 刷新ConfigurableApplicationContext
- 容器刷新後動做
- SpringApplicationRunListeners發佈finish事件
5、BeanFactory中Bean生命週期
大體來說:
- 建立Bean實例
- 設置屬性值以及對其餘Bean的引用
- 初始化 - init-method
- 放入緩衝池(單例),多例交給調用者(後續該Bean的生命週期由垃圾回收來定了)
- 銷燬Bean - destroy - method
6、AOP
兩種代理:
- JDK:基於接口
- 原理:動態代理 + 反射
- 定義一個類XxHandler,實現InvocationHandler接口,裏邊包含真實對象的實例(其實是一個Object,具體真實對象在運行期賦值給Object),並使用反射調用真實對象的指定方法
- 使用Proxy.newProxyInstance(ClassLoader, interfaces, InvocationHandler)建立代理對象,以後調用相應的真實對象的方法便可。
- 因爲該方法的第二個對象是interface,因此JDK只能基於接口實現動態代理。
- CGLib:基於類
- 原理:動態生成字節碼技術,即爲將要攔截的類動態生成子類,而後在子類中攔截全部父類的調用並順勢織入橫切邏輯。
- 因爲是建立子類,因此不能代理目標類中的private和final方法。
比較:
- CGLib建立代理對象花費的時間長於JDK,由於要動態生成子類
- CGLib建立好的代理對象的性能因爲JDK