Spring Bean的生命周期以及IOC源碼解析

IOC源碼這一塊太多只能講個大概吧,建議還是去買本Spring IOC源碼解析的書來看比較好,我也是自己看源代碼以及視頻整理的筆記

Bean的生命周期大概可以分為四個階段,具體的等會再說,先看看IOC的源碼吧

1、bean的創建

2、bean的屬性賦值

3、bean的初始化

4、bean的銷毀

IOC容器源碼解析

我們創建容器以new?AnnotationConfigApplicationContext(Config.class)為示例,我們點開源代碼,看一下

其實做了挺多事的,在父類的的無參構造函數當中,就創建了一個BeanFactory的實例,其實可以去看一下這個類的無參構造函數,其實加載了很多必備的Bean到容器當中,例如之前提到過的一些常用的BeanPostProcessor,這里就不多說了,不然博客會太長了

接下來就是第一個方法register(componentClasses)解析配置類的注解,并且創建了BeanFactory的實例(org.springframework.beans.factory.support.DefaultListableBeanFactory的實例)并且將配置類注入到容器中

方法點進去之后能看到

?我們進到注冊Bean的方法(BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);)里面

我們看一下是怎么注入的

其實就是將對象包裝成BeanDefinition對象,然后添加到ConcurrentHashMap當中。

第二部,進入到refresh()方法,但是該方法位于父類的org.springframework.context.support.AbstractApplicationContext.class的515行,這個是一個刷新方法,將我們的業務Bean注入進去

無論是通過哪種創建Spring?的ioc容器都會執行這個refresh方法。大致的主要方法如下,不過有些方法的細節就不講了,IOC過于龐大,懂個大概就差不多了,但是方法具體是干嘛的會一個一個講

prepareRefresh()

1)、initPropertySources()初始化一些屬性設置;子類自定義個性化的屬性設置方法;

2)、getEnvironment().validateRequiredProperties();檢驗屬性的合法等

3)、earlyApplicationEvents= new LinkedHashSet<ApplicationEvent>();保存容器中的一些早期的事件;

obtainFreshBeanFactory()

獲取到BeanFactory對象

prepareBeanFactory(beanFactory)

設置一下BeanFactory對象一些屬性

???????? 1)、設置BeanFactory的類加載器、支持表達式解析器...

???????? 2)、添加部分BeanPostProcessor【ApplicationContextAwareProcessor】

???????? 3)、設置忽略的自動裝配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;

???????? 4)、注冊可以解析的自動裝配;我們能直接在任何組件中自動注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext

???????? 5)、添加BeanPostProcessor【ApplicationListenerDetector】

???????? 6)、添加一些loadTimeWeaver;

???????? 7)、給BeanFactory中注冊一些能用的組件;

?????????????????? environment【ConfigurableEnvironment】、

?????????????????? systemProperties【Map<String, Object>】、

?????????????????? systemEnvironment【Map<String, Object>】

postProcessBeanFactory(beanFactory)

BeanFactory完成的后置工作,當前為空,但是可以繼承當前類,在子類中可以實現這個方法

invokeBeanFactoryPostProcessors(beanFactory)

加載并執行BeanFactoryPostProcessor以及BeanDefinitionRegistryPostProcessor這兩個接口的兩個實現方法

1、postProcessBeanFactory()

2、postProcessBeanDefinitionRegistry():

這個方法里面做了很多加載,這里就不展示,自行去看源碼吧

initMessageSource()

注冊一個MessageSource的對象,但是這個Bean并沒有加載到之前的那個Map當中,而是加載到一個緩存的Map當中,用于解決循環依賴

initApplicationEventMulticaster()

初始化一個派發器,跟上面那個差不多,只是對象不一樣

onRefresh()

跟之前的那個postProcessorBeanFactory方法差不多,留給子類實現

registerListeners()

注冊監聽器,實現ApplicationListener<?>接口,并指定時在什么時候加載即指定ContextEvent

finishBeanFactoryInitialization(beanFactory)

這個就是加載所有業務單實例Bean的方法,并且生命周期都會在這里執行,首先會配置一些BeanFactory的一些屬性,然后在加載業務Bean

第一部分優先獲取Bean名稱的一些定義信息getMergedLocalBeanDefinition(beanName),然后先處理實現FactoryBean的Bean

點進去getBean(beanName)之后,調用方法?doGetBean(name, null, null, false),這個方法就不貼截圖了,代碼太多不好截圖,可以自己去對照這源碼看,就講調用了哪個方法就好了。

Object sharedInstance = getSingleton(beanName)?從緩存的Bean中去獲取看看在不在,如果存在的話就直接獲取(會去校驗FactoryBean緩存中是否存在),不存在就執行else方法

如果緩存中不存在的話,就是一個新的Bean等待創建

運行到了markBeanAsCreated(String beanName),這個是用來標記當前beanName已經存在了,將beanName添加到alreadyCreated集合當中,然后運行到了下面

然后繼續執行

進入到createBean()方法后,有個獲取代理的方法,這個方法就得講一下,跟Spring的AOP以及事務有關

Object bean = resolveBeforeInstantiation(beanName, mbdToUse)講解:

我們點開查看一下這個方法,有個createProxy()創建代理方法

進入到創建代理的方法里面,我們看一下

我們點開getProxy方法,會返回一個createAopProxy().getProxy(classLoader);對象,我們依次點開后,在使用AOP到底是JDK動態代理還是CGLIB代理的關鍵所在

好了,代理的那個方法差不多了,我們改回到正題了

我們進入到Object beanInstance = doCreateBean(beanName, mbdToUse, args);

有個BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);這個是創建BeanWrapper的包裝類,在createBeanInstance方法中最后會執行instantiateBean()

我們進入到這個instantiate(),最后有個BeanUtils.instantiateClass(constructorToUse)方法用來創建對象,這就不深入的討論了,大家可以自己去看

然后包裝一個BeanWrapperImpl對象,最后返回出去;創建好后,進行屬性賦值以及Bean的初始化,在屬性賦值的方法里面有個InstantiationAwareBeanPostProcessors方法執行

我們看下初始化方法

Bean的初始化,會先加載Aware,然后調用BeanPostProcessor的前置方法,然后加載初始化方法,再加載BeanPostProcessor的后置方法

這個方法基本就加載完了

finishRefresh()

加載完業務Bean的一些工作

resetCommonCaches()

這個是處于finally代碼塊的方法用來清除創建時臨時緩存數據

Bean生命周期

在上面IOC分析里面已經提到了Bean的創建以及屬性賦值了

接下來就是初始化以及銷毀

初始化

初始化使用的方法有三種

1@Bean(initMethod = "")調用指定初始化方法

2、在類中設置@PostConstruct注解

3、實現InitializingBean接口,實現afterPropertiesSet()方法

銷毀

對應的銷毀也有三種

1、@Bean(destroyMethod= "")調用指定銷毀方法

2、在類中設置@PreDestroy注解

3、實現DisposableBean接口,實現destroy()方法

銷毀在容器關閉是時候執行

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/537143.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537143.shtml
英文地址,請注明出處:http://en.pswp.cn/news/537143.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python3繪圖_python3繪圖示例2(基于matplotlib:柱狀圖、分布圖、三角圖等)

#!/usr/bin/env python# -*- coding:utf-8 -*-from matplotlib import pyplot as pltimport numpy as npimport pylabimport os,sys,time,math,random# 圖1-給已有的圖加上刻度filer‘D:\jmeter\jmeter3.2\data\Oracle數據庫基礎.png‘arrnp.array(file.getdata()).reshape(fil…

bzoj4152-[AMPPZ2014]The_Captain

Description 給定平面上的n個點&#xff0c;定義(x1,y1)到(x2,y2)的費用為min(|x1-x2|,|y1-y2|)&#xff0c;求從1號點走到n號點的最小費用。 Input 第一行包含一個正整數n(2<n<200000)&#xff0c;表示點數。 接下來n行&#xff0c;每行包含兩個整數x[i],yi&#xff0c;…

python日志統計_python試用-日志統計

最近兩天嘗試用python代替bash寫Linux Shell腳本來統計日志。發現python寫起來比bash更簡單和容易閱讀&#xff0c;發現不少驚喜。所以寫了一個粗糙的腳本來統計日志。目標1、通過簡單命令和腳本統計事件發生數2、日志限定文本類型假定環境日志文件&#xff1a;1.logtest:aaa,1…

Spring AOP兩種使用方式以及如何使用解析

AOP是一種面向切面編程思想&#xff0c;也是面向對象設計&#xff08;OOP&#xff09;的一種延伸。 在Spring實現AOP有兩種實現方式&#xff0c;一種是采用JDK動態代理實現&#xff0c;另外一種就是采用CGLIB代理實現&#xff0c;Spring是如何實現的在上篇已經講到了Spring Be…

如何用python生成可執行程序必須經過_python怎么生成可執行文件

.py文件&#xff1a;對于開源項目或62616964757a686964616fe58685e5aeb931333363393664者源碼沒那么重要的&#xff0c;直接提供源碼&#xff0c;需要使用者自行安裝Python并且安裝依賴的各種庫。(Python官方的各種安裝包就是這樣做的).pyc文件&#xff1a;有些公司或個人因為機…

Jmeter 老司機帶你一小時學會Jmeter

Jmeter的安裝 官網下載地址&#xff1a;http://jmeter.apache.org/download_jmeter.cgi 作為Java應用&#xff0c;是需要JDK環境的&#xff0c;因此需要下載安裝JAVA&#xff0c;并且作必要的的環境變量配置。 一、bin目錄 examples:    目錄中有CSV樣例 jmeter.bat/jmeter…

MongoDB位運算基本使用以及位運算應用場景

最近在公司業務上用到了二進制匹配數據&#xff0c;但是MongoDB進行二進制運算&#xff08;Bitwise&#xff09;沒用過&#xff0c;網上博客文章少&#xff0c;所以就上官網看API&#xff0c;因此記錄一下&#xff0c;順便在普及一下使用二進制位運算的一些應用。 在MongoDB的…

好用的下拉第三方——nicespinner

1.簡介 GitHub地址&#xff1a;https://github.com/arcadefire/nice-spinner Gradle中添加&#xff1a; allprojects {repositories {...maven { url "https://jitpack.io" }} }dependencies {implementation com.github.arcadefire:nice-spinner:1.3.7 }2.使用 xml文…

Mybatis配置文件參數定義

官網有時候進不去&#xff0c;所以就記錄一下Mybatis的配置文件的各項參數定義&#xff0c;大家也可以上官網查詢&#xff0c;官方文檔&#xff0c;進不進的去看各自的緣分了 properties 定義配置&#xff0c;在這里配置的屬性可以在整個配置文件使用&#xff1b;可以加載指定…

python和java后期發展_Python與java的發展前景誰最大

Python和Java是目前IT行業內兩大編程語言&#xff0c;很多人都喜歡拿來比較&#xff0c;一個是后起之秀&#xff0c;潛力無限&#xff1b;一個是行業經典&#xff0c;成熟穩定。對于許多想從事IT行業的同學來說&#xff0c;這兩門語言真的很難抉擇。那么&#xff0c;Python和Ja…

JDK源碼學習筆記——Enum枚舉使用及原理

一、為什么使用枚舉 什么時候應該使用枚舉呢&#xff1f;每當需要一組固定的常量的時候&#xff0c;如一周的天數、一年四季等。或者是在我們編譯前就知道其包含的所有值的集合。 利用 public final static 完全可以實現的功能&#xff0c;為什么要使用枚舉&#xff1f; public…

Mybatis源碼日志模塊分析

看源碼需要先下載源碼&#xff0c;可以去Mybatis的github上的倉庫進行下載&#xff0c;Mybatis 這次就先整理一下日志這一塊的源碼分析&#xff0c;這塊相對來說比較簡單而且這個模塊是Mybatis的基礎模塊。 之前的文章有談到過Java的日志實現&#xff0c;大家也可以參考一下&…

python手機端給電腦端發送數據_期貨交易軟件有哪些比較好用?分手機端和電腦端...

一、電腦端交易軟件期貨電腦端交易軟件目前市場上用的最多的是文華財經和博易大師&#xff0c;這兩個軟件都是免費交易使用的。從投資者使用角度來看&#xff0c;目前電腦端文華財經的評價比博易大師高一些。當然每個投資者有自己的使用習慣&#xff0c;博易大師也有自己優點&a…

Find the Difference(leetcode389)

2019獨角獸企業重金招聘Python工程師標準>>> Given two strings s and t which consist of only lowercase letters. String t is generated by random shuffling string s and then add one more letter at a random position. Find the letter that was added in …

Mybatis源碼之數據源模塊分析

先來看看java純jdbc查詢數據的示例&#xff1a; try {//加載對應的驅動類Class.forName("com.mysql.cj.jdbc.Driver");//創建連接Connection connection DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezoneUTC", "roo…

reactnative 獲取定位_[RN] React Native 獲取地理位置

import React, {Component} from react;import {StyleSheet, Text, View}from react-native;exportdefault classTestGeo extends Component {state{longitude:,//經度latitude: ,//緯度city: ,district:,street:,position:,//位置名稱};componentWillMount () >{this.getPo…

第二沖刺階段第三天

查閱資料&#xff0c;修改控件界面轉載于:https://www.cnblogs.com/gyy0/p/10066452.html

Mybatis源碼之緩存模塊分析

緩存這個東西在很多應用中都能看到它們的身影&#xff0c;這次就講講在Mybatis中的緩存是怎么應用的&#xff0c;雖然說吧Mybatis中的緩存基本不怎么用&#xff0c;用的更多是第三方組件redis、MongoDB、MemCache等等。 Mybatis的緩存是基于Map實現的&#xff0c;從緩存中讀寫…

Mybatis源碼之核心流程分析

終于談到了Mybatis最核心的東西了&#xff0c;最核心的就是通過配置XML文件或注解中的SQL&#xff0c;直接調用接口就能執行配置好的SQL語句并封裝成對應的返回類型的數據。 先看一下Mybatis使用示例&#xff1a; //創建Builder對象 SqlSessionFactoryBuilder builder new S…

mimakatz用法_兩步完成利用procdump64+mimikatz獲取win用戶密碼

使用procdump64mimikatz可實現從內存中獲取明文密碼工具鏈接&#xff1a;https://pan.baidu.com/s/1gNc9qLcNSNBohIVrAiqShw 密碼&#xff1a;fc38首先得先獲取到內存文件lsass.exe進程, 它用于本地安全和登陸策略,一般在進程管理器中能看到, 比如這樣1.導出lsass.exeprocdump6…