1. 程式人生 > >Spring Security Config 5.1.2 原始碼解析 -- 工具類 AutowireBeanFactoryObjectPostProcessor

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);
			}
		}
	}

}