Spring Security Config 5.1.2 原始碼解析 -- 工具類 AutowireBeanFactoryObjectPostProcessor
概述
Spring Security
的配置機制會使用到很多物件,比如WebSecurity
,ProviderManager
,各個安全Filter
等。這些物件的建立並不是通過bean
定義的形式被容器發現和註冊進入容器的。而是由Spring Security
配置機制使用Java new
操作符建立。但對於這些並未被容器管理的物件,Spring Security
配置機制也稱之為bean
,並且希望它們也經歷跟容器bean
同樣的生命週期,也能注入相應的依賴,從而進入準備好被使用的狀態。為達成這個目標,Spring Security
配置機制提供了一個工具類AutowireBeanFactoryObjectPostProcessor
工具類AutowireBeanFactoryObjectPostProcessor
本身會被註冊成為容器的一個bean
,並且它實現了Spring bean
基本的DisposableBean
,SmartInitializingSingleton
生命週期介面,也就是說它會經歷容器標準的生命週期方法呼叫。在此基礎之上,AutowireBeanFactoryObjectPostProcessor
又實現了另外一個介面ObjectPostProcessor
,這是一個Spring Security
自己定義的介面,用來初始化某個新建的物件,通常就是呼叫其可能帶有的跟Aware
方法,InitializingBean#afterPropertiesSet()
DisposableBean#destroy()
這樣的方法也能被執行。
具體我們通過程式碼來分析。
AutowireBeanFactoryObjectPostProcessor
被註冊為容器bean
當使用了註解@EnableWebSecurity
,或者@EnableGlobalMethodSecurity
時,AutowireBeanFactoryObjectPostProcessor
會被註冊為一個容器bean
:
// @EnableWebSecurity 註解程式碼片段,可以看到該註解隱含使用了@EnableGlobalMethodSecurity
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
/**
* Controls debugging support for Spring Security. Default is false.
* @return if true, enables debug support with Spring Security
*/
boolean debug() default false;
}
// @EnableGlobalAuthentication 註解程式碼片段,可以看到它匯入了類 AuthenticationConfiguration
@Import(AuthenticationConfiguration.class)
@Configuration
public @interface EnableGlobalAuthentication {
}
從上面的程式碼片段來看,不管使用了@EnableWebSecurity
還是@EnableGlobalAuthentication
,最終都會匯入類AuthenticationConfiguration
:
@Configuration
@Import(ObjectPostProcessorConfiguration.class) // 匯入了類 ObjectPostProcessorConfiguration
public class AuthenticationConfiguration {
// 省略無關程式碼實現
}
而類AuthenticationConfiguration
又匯入了類ObjectPostProcessorConfiguration
,ObjectPostProcessorConfiguration
進一步註冊了bean AutowireBeanFactoryObjectPostProcessor
:
@Configuration
public class ObjectPostProcessorConfiguration {
// 這裡的引數beanFactory會被自動注入成當前Spring bean容器
@Bean
public ObjectPostProcessor<Object> objectPostProcessor(
AutowireCapableBeanFactory beanFactory) {
return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
}
}
AutowireBeanFactoryObjectPostProcessor
的任務
package org.springframework.security.config.annotation.configuration;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.util.Assert;
final class AutowireBeanFactoryObjectPostProcessor
implements ObjectPostProcessor<Object>, DisposableBean, SmartInitializingSingleton {
private final Log logger = LogFactory.getLog(getClass());
private final AutowireCapableBeanFactory autowireBeanFactory;
private final List<DisposableBean> disposableBeans = new ArrayList<>();
private final List<SmartInitializingSingleton> smartSingletons = new ArrayList<>();
// 使用指定的 autowireBeanFactory 構造物件
// autowireBeanFactory 通常是 Spring bean 容器
public AutowireBeanFactoryObjectPostProcessor(
AutowireCapableBeanFactory autowireBeanFactory) {
Assert.notNull(autowireBeanFactory, "autowireBeanFactory cannot be null");
this.autowireBeanFactory = autowireBeanFactory;
}
// 對某個剛剛建立的物件 object 執行這裡所謂的 post-process 流程 :
// 1. 使用指定的 autowireBeanFactory 對該物件 object 執行初始化過程;
// 2. 使用指定的 autowireBeanFactory 對該物件 object 執行依賴注入過程;
// 3. 如果該物件 object 是一個 DisposableBean , 則將它記錄下來,在當前物件的destroy()
// 被呼叫時,它們的 destroy() 方法也都會被呼叫;
// 4. 如果該物件 object 是一個 SmartInitializingSingleton , 則將它記錄下來,
// 在當前物件的 afterSingletonsInstantiated () 被呼叫時,它們的 afterSingletonsInstantiated()
// 方法也都會被呼叫;
@SuppressWarnings("unchecked")
public <T> T postProcess(T object) {
if (object == null) {
return null;
}
T result = null;
try {
// 使用容器autowireBeanFactory標準初始化方法initializeBean()初始化物件 object
result = (T) this.autowireBeanFactory.initializeBean(object,
object.toString());
}
catch (RuntimeException e) {
Class<?> type = object.getClass();
throw new RuntimeException(
"Could not postProcess " + object + " of type " + type, e);
}
// 使用容器autowireBeanFactory標準依賴注入方法autowireBean()處理 object物件的依賴注入
this.autowireBeanFactory.autowireBean(object);
if (result instanceof DisposableBean) {
// 記錄一個 DisposableBean 物件
this.disposableBeans.add((DisposableBean) result);
}
if (result instanceof SmartInitializingSingleton) {
// 記錄一個 SmartInitializingSingleton 物件
this.smartSingletons.add((SmartInitializingSingleton) result);
}
return result;
}
// SmartInitializingSingleton 介面定義的生命週期方法,在被呼叫時也回撥用被記錄的實現了
// SmartInitializingSingleton 介面的那些物件的方法 afterSingletonsInstantiated()
@Override
public void afterSingletonsInstantiated() {
for (SmartInitializingSingleton singleton : smartSingletons) {
singleton.afterSingletonsInstantiated();
}
}
// DisposableBean 介面定義的生命週期方法,在被呼叫時也回撥用被記錄的實現了
// DisposableBean 介面的那些物件的方法 destroy()
public void destroy() throws Exception {
for (DisposableBean disposable : this.disposableBeans) {
try {
disposable.destroy();
}
catch (Exception error) {
this.logger.error(error);
}
}
}
}