調用 WebSecurity 的 build() 方法返回一個 FilterChainProxy 實例。
調用 HttpSecurity 的 build() 方法返回一個 SecurityFilterChain 實例(DefaultSecurityFilterChain 是 SecurityFilterChain 的唯一實現類)。
WebSecurity 和 HttpSecurity 是如何初始化的?
需要重新從 FilterChainProxy 初始化過程開始看,參考前面文章 啟動時初始化FilterChainProxy 。
WebSecurity 初始化
在執行 WebSecurityConfiguration 的 setFilterChainProxySecurityConfigurer(...) 方法時,通過 new 關鍵字實例化了 WebSecurity。
至此 WebSecurity 就初始化完成了。
HttpSecurity 初始化
步驟一
從 WebSecurityConfiguration 的 setFilterChainProxySecurityConfigurer(...) 方法開始執行。
這次重點看上圖的三處位置:
1. 上圖標①位置是一個 @Value 注解,里面是 Spring SpEL 表達式,其作用是調用 AutowiredWebSecurityConfigurersIgnoreParents 的 getWebSecurityConfigurers() 方法,並將返回賦值給上圖中標②位置的 webSecurityConfigurers
2. 上圖標②位置的 webSecurityConfigurers 已經被賦值了。查看 AutowiredWebSecurityConfigurersIgnoreParents 的 getWebSecurityConfigurers() 方法體,其返回值是所有 WebSecurityConfigurer 實例的 List 集合。
3. 上圖標③位置,是調用 WebSecurity 的 apply(...) 方法,其作用是將 webSecurityConfigurers 中的元素添加到 WebSecurity 的屬性 configurers 中(見下圖 AbstractConfiguredSecurityBuilder 是 WebSecurity 父類)。
到此總結一下:在 WebSecurity 的 configurers 屬性中保存了所有的 WebSecurityConfigurer 實例
步驟二
繼續往下梳理,接着執行 WebSecurityConfiguration 的 springSecurityFilterChain() 方法:
會調用 WebSecurity 的 build() 方法,webSecurity 的 build() 方法梳理參考前面的文章 通過WebSecurity構建FilterChainProxy 。
在 WebSecurity 的 build() 方法執行過程中,會走到 dobuild() 方法體中,這次重點關注其中的 init() 這一步:
查看 init() 的方法體:
在 init() 方法體中先調用了 getConfigurers() 方法,獲取一個集合,遍歷並調用集合中元素的 init(...) 方法。查看 getConfigurers() 方法體可以看到是從 WebSecurity 的屬性 configurers 中獲取元素。在前面步驟一中已經知道了 configurers 就是 WebSecurityConfigurer 實例的集合。
因而下一步,就是查看 WebSecurityConfigurer 的 init(...) 方法。
到此總結一下:獲取 WebSecurity 的屬性 configurers,並遍歷其中的 WebSecurityConfigurer 實例,調用 WebSecurityConfigurer 的 init(...) 方法。
步驟三
因 WebSecurityConfigurerAdapter 是 WebSecurityConfigurer 的實現類,因而到 WebSecurityConfigurerAdapter 中查看 init(..) 方法體:
通過調用 getHttp() 方法獲取了 HttpSecurity 的實例,進入到 getHttp() 方法中查看:
通過 new 關鍵字實例化了 HttpSecurity。
至此 HttpSecurity 初始化就完成了。