創(chuàng)建 bean
在經(jīng)歷過 AbstractAutowireCapableBeanFactory#createBean
中的 resolveBeforeInstantiation
方法后奈辰,程序有兩個選擇,如果創(chuàng)建了代理或者說重寫了 InstantiationAwareBeanPostProcessor
的 postProcessBeforeInstantiation
方法并在方法 postProcessBeforeInstantiation
中改變了 bean
赏酥,則直接返回就可以了甸箱,否則需要進行常規(guī) bean
的創(chuàng)建糯而。而這常規(guī) bean
的創(chuàng)建就是在 doCreateBean
中完成的账嚎。
AbstractAutowireCapableBeanFactory#doCreateBean
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) { // 1
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) { // 2
// 根據(jù)指定 bean 使用對應(yīng)的策略創(chuàng)建新的實例涂身,如:工廠方法雄卷、構(gòu)造函數(shù)自動注入、簡單初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 應(yīng)用 MergedBeanDefinitionPostProcessor
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); // 3
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 4
// 是否需要提前曝光:單例 & 允許循環(huán)依賴 & 當前 bean 正在創(chuàng)建中蛤售,檢測循環(huán)依賴
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 為了避免后期循環(huán)依賴丁鹉,可以在 bean 初始化完成前將創(chuàng)建實例的 ObjectFactory 加入工廠
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
// 對 bean 再一次依賴引用妒潭,主要應(yīng)用 SmartInstantiationAware BeanPostProcessor,
// 其中我們熟知的 AOP 就是在這里將 advice 動態(tài)織入 bean 中,若沒有直接返回 bean揣钦,不做任何處理
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 對 bean 進行填充雳灾,將各個屬性值注入,其中冯凹,可能存在依賴于其他 bean 的屬性谎亩,則會遞歸初始依賴 bean
// 5
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 調(diào)用初始化方法,比如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
// earlySingletonReference 只有在檢測到有循環(huán)依賴的情況下才會不為空
// 6
if (earlySingletonReference != null) {
// 如果 esposedObject 沒有在初始化方法中被改變宇姚,就是沒有被增強
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 檢測依賴
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// 因為 bean 創(chuàng)建后其所依賴的 bean 一定是已經(jīng)創(chuàng)建的匈庭,
// actualDependentBeans 不為空則表示當前 bean 創(chuàng)建后其依賴的 bean 卻沒有
// 全部創(chuàng)建完,也就是說存在循環(huán)依賴
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
// 根據(jù) scopes 注冊 bean
registerDisposableBeanIfNecessary(beanName, bean, mbd); // 7
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject; // 8
}
如果是單例則需要首先清除緩存
-
實例化 bean浑劳,將
BeanDefinition
轉(zhuǎn)換為BeanWrapper
轉(zhuǎn)換是一個復(fù)雜的過程阱持,但是我們可以嘗試概括大致的功能:
- 如果存在工廠方法則使用工廠方法進行初始化
- 一個類有多個構(gòu)造函數(shù),每個構(gòu)造函數(shù)都有不同的參數(shù)魔熏,所以需要根據(jù)參數(shù)鎖定構(gòu)造函數(shù)并進行初始化
- 如果既不存在工廠方法也不存在帶有參數(shù)的構(gòu)造函數(shù)衷咽,則使用默認的構(gòu)造函數(shù)進行 bean 的實例化
-
MergedBeanDefinitionPostProcessor的應(yīng)用
bean合并后的處理,Autowired注解正是通過此方法實現(xiàn)諸如類型的預(yù)解析蒜绽。
-
依賴處理
在Spring中會有循環(huán)依賴的情況镶骗,例如,當A中含有B的屬性躲雅,而B中又含有A的屬性時就會構(gòu)成一個循環(huán)依賴卖词,此時如果A和B都是單例,那么在Spring中的處理方式就是當創(chuàng)建B的時候吏夯,涉及自動注入A的步驟時此蜈,并不是直接去再次創(chuàng)建A,而是通過放入緩存中的ObjectFactory來創(chuàng)建實例噪生,這樣就解決了循環(huán)依賴的問題裆赵。
屬性填充。將所有屬性填充至bean的實例中
-
循環(huán)依賴檢查
Sping 中解決循環(huán)依賴只對單例有效跺嗽,而對于 prototype 的 bean战授,Spring 沒有好的解決辦法,唯一要做的就是拋出異常桨嫁。在這個步驟里面會檢測已經(jīng)加載的 bean 是否已經(jīng)出現(xiàn)了依賴循環(huán)植兰,并判斷是否需要拋出異常。
-
注冊DisposableBean
如果配置了destroy-method璃吧,這里需要注冊以便于在銷毀時候調(diào)用楣导。
完成創(chuàng)建并返回
創(chuàng)建 bean 的實例 (createBeanInstance)
/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return BeanWrapper for the new instance
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析 class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 如果工廠方法不為空則使用工廠方法初始化策略
if (mbd.getFactoryMethodName() != null) { // 1
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 2
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 一個類有多個構(gòu)造函數(shù),每個構(gòu)造函數(shù)都有不同的參數(shù)畜挨,所以調(diào)用前需要先根據(jù)參數(shù)鎖定構(gòu)造函數(shù)或?qū)?yīng)的工廠方法
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 如果已經(jīng)解析過則使用解析好的構(gòu)造函數(shù)方法不需要再次鎖定
if (resolved) {
if (autowireNecessary) {
// 構(gòu)造函數(shù)自動注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默認構(gòu)造函數(shù)構(gòu)造
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
// 需要根據(jù)參數(shù)解析構(gòu)造函數(shù)
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 構(gòu)造函數(shù)自動注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// 使用默認構(gòu)造函數(shù)構(gòu)造
return instantiateBean(beanName, mbd);
}
- 如果在
RootBeanDefinition
中存在factoryMethodName
屬性筒繁,或者說在配置文件中配置了factory-method
噩凹,那么 Spring 會嘗試使用instantiateUsingFactoryMethod(beanName, mbd, args)
方法根據(jù)RootBeanDefinition
中的配置生成bean的實例。 - 解析構(gòu)造函數(shù)并進行構(gòu)造函數(shù)的實例化毡咏。因為一個 bean 對應(yīng)的類中可能會有多個構(gòu)造函數(shù)翩活,而每個構(gòu)造函數(shù)的參數(shù)不同蔓挖,Spring 在根據(jù)參數(shù)及類型去判斷最終會使用哪個構(gòu)造函數(shù)進行實例化贪壳。但是筒愚,判斷的過程是個比較消耗性能的步驟,所以采用緩存機制恢总,如果已經(jīng)解析過則不需要重復(fù)解析而是直接從
RootBeanDefinition
中的屬性resolvedConstructorOrFactoryMethod
緩存的值去取落恼,否則需要再次解析,并將解析的結(jié)果添加至RootBeanDefinition
中的屬性resolvedConstructorOrFactoryMethod
中离熏。
### autowireConstructor
對于實例的創(chuàng)建Spring中分成了兩種情況,一種是通用的實例化戴涝,另一種是帶有參數(shù)的實例化滋戳。帶有參數(shù)的實例化過程相當復(fù)雜,因為存在著不確定性啥刻,所以在判斷對應(yīng)參數(shù)上做了大量工作奸鸯。
/**
* "autowire constructor" (with constructor arguments by type) behavior.
* Also applied if explicit constructor argument values are specified,
* matching all remaining arguments with beans from the bean factory.
* <p>This corresponds to constructor injection: In this mode, a Spring
* bean factory is able to host components that expect constructor-based
* dependency resolution.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param ctors the chosen candidate constructors
* @param explicitArgs argument values passed in programmatically via the getBean method,
* or {@code null} if none (-> use constructor argument values from bean definition)
* @return BeanWrapper for the new instance
*/
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
這邊的代碼量太大了,不太適合貼出來解析可帽,各位最好還是去 idea 里面進行查看娄涩,書中作者也覺得這段不符合 Spring 那種『將復(fù)雜的邏輯分解,分成N個小函數(shù)的嵌套映跟,每一層都是對下一層邏輯的總結(jié)及概要蓄拣,這樣使得每一層的邏輯會變得簡單容易理解』的規(guī)律。我這里就說明一下整體流程努隙,每段流程貼出對應(yīng)的代碼球恤。
構(gòu)造函數(shù)參數(shù)的確定
-
根據(jù)explicitArgs參數(shù)判斷
如果傳入的參數(shù)
explicitArgs
不為空,那邊可以直接確定參數(shù)荸镊,因為explicitArgs
參數(shù)是在調(diào)用 Bean 的時候用戶指定的咽斧,在BeanFactory
類中存在這樣的方法:
Object getBean(String name, Object... args) throws BeansException;
在獲取 bean 的時候,用戶不但可以指定 bean 的名稱還可以指定 bean 所對應(yīng)類的構(gòu)造函數(shù)或者工廠方法的方法參數(shù)躬存,主要用于靜態(tài)工廠方法的調(diào)用张惹,而這里是需要給定完全匹配的參數(shù)的,所以岭洲,便可以判斷宛逗,如果傳入?yún)?shù)explicitArgs
不為空,則可以確定構(gòu)造函數(shù)參數(shù)就是它盾剩。// explicitArgs 通過 getBean 方法傳入 // 如果 getBean 方法調(diào)用的時候指定方法參數(shù)那么直接使用 if (explicitArgs != null) { argsToUse = explicitArgs }
-
緩存中獲取
構(gòu)造函數(shù)參數(shù)已經(jīng)記錄在緩存中拧额,那么便可以直接拿來使用碑诉。而且,這里要提到的是侥锦,在緩存中緩存的可能是參數(shù)的最終類型也可能是參數(shù)的初始類型进栽,例如:構(gòu)造函數(shù)參數(shù)要求的是 int 類型,但是原始的參數(shù)值可能是String類型的“1”恭垦,那么即使在緩存中得到了參數(shù)快毛,也需要經(jīng)過類型轉(zhuǎn)換器的過濾以確保參數(shù)類型與對應(yīng)的構(gòu)造函數(shù)參數(shù)類型完全對應(yīng)。
else { // 如果在 getBean 方法時候沒有指定則嘗試從配置文件中解析 Object[] argsToResolve = null; // 嘗試從緩存中獲取 synchronized (mbd.constructorArgumentLock) { constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { // Found a cached constructor... // 從緩存中取 argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { // 配置的構(gòu)造函數(shù)參數(shù) argsToResolve = mbd.preparedConstructorArguments; } } } // 如果緩存中存在 if (argsToResolve != null) { // 解析參數(shù)類型番挺,如給定方法的構(gòu)造函數(shù) A(int, int) 則通過此方法后就會把配置匯中的 ("1", "1") 轉(zhuǎn)換為 (1, 1) // 緩存中的值可能是原始值也可能是最終值 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve); } }
-
配置文件獲取
如果不能根據(jù)傳入的參數(shù)
explicitArgs
確定構(gòu)造函數(shù)的參數(shù)也無法在緩存中得到相關(guān)信息唠帝,那么只能開始新一輪的分析了。
分析從獲取配置文件中配置的構(gòu)造函數(shù)信息開始玄柏,經(jīng)過之前的分析襟衰,我們知道,Spring中配置文件中的信息經(jīng)過轉(zhuǎn)換都會通過BeanDefinition
實例承載粪摘,也就是參數(shù)mbd
中包含瀑晒,那么可以通過調(diào)用mbd.getConstructorArgumentValues()
來獲取配置的構(gòu)造函數(shù)信息。有了配置中的信息便可以獲取對應(yīng)的參數(shù)值信息了徘意,獲取參數(shù)值的信息包括直接指定值苔悦,如:直接指定構(gòu)造函數(shù)中某個值為原始類型 String 類型,或者是一個對其他 bean 的引用椎咧,而這一處理委托給resolveConstructorArguments
方法玖详,并返回能解析到的參數(shù)的個數(shù)。// Need to resolve the constructor. boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { // 提取配置文件中的配置的構(gòu)造函數(shù)參數(shù) ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); // 用于承載解析后的構(gòu)造函數(shù)參數(shù)的值 resolvedValues = new ConstructorArgumentValues(); // 能解析到的參數(shù)個數(shù) minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); }
構(gòu)造函數(shù)的確認
經(jīng)過了第一步后已經(jīng)確定了構(gòu)造函數(shù)的參數(shù)勤讽,接下來的任務(wù)就是根據(jù)構(gòu)造函數(shù)參數(shù)在所有構(gòu)造函數(shù)中鎖定對應(yīng)的構(gòu)造函數(shù)蟋座,而匹配的方法就是根據(jù)參數(shù)個數(shù)匹配,所以在匹配之前需要先對構(gòu)造函數(shù)按照public構(gòu)造函數(shù)優(yōu)先參數(shù)數(shù)量降序脚牍、非public構(gòu)造函數(shù)參數(shù)數(shù)量降序蜈七。這樣可以在遍歷的情況下迅速判斷排在后面的構(gòu)造函數(shù)參數(shù)個數(shù)是否符合條件。
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
// 排序給定的構(gòu)造函數(shù)莫矗,public 構(gòu)造函數(shù)優(yōu)先參數(shù)數(shù)量排序飒硅、非 public 構(gòu)造函數(shù)參數(shù)數(shù)量降序
AutowireUtils.sortConstructors(candidates);
由于在配置文件中并不是唯一限制使用參數(shù)位置索引的方式去創(chuàng)建,同樣還支持指定參數(shù)名稱進行設(shè)定參數(shù)值的情況作谚,如<constructor-arg name="aa">
三娩,那么這種情況就需要首先確定構(gòu)造函數(shù)中的參數(shù)名稱。
獲取參數(shù)名稱可以有兩種方式
-
通過注解的方式直接獲取妹懒,
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
-
使用Spring中提供的工具類
ParameterNameDiscoverer
來獲取雀监。構(gòu)造函數(shù)、參數(shù)名稱、參數(shù)類型会前、參數(shù)值都確定后就可以鎖定構(gòu)造函數(shù)以及轉(zhuǎn)換對應(yīng)的參數(shù)類型了好乐。if (paramNames == null) { ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { paramNames = pnd.getParameterNames(candidate); } }
根據(jù)確定的構(gòu)造函數(shù)轉(zhuǎn)換對應(yīng)的參數(shù)類型
主要是使用Spring中提供的類型轉(zhuǎn)換器或者用戶提供的自定義類型轉(zhuǎn)換器進行轉(zhuǎn)換。
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring);
構(gòu)造參數(shù)不確定性的驗證
當然瓦宜,有時候即使構(gòu)造函數(shù)蔚万、參數(shù)名稱、參數(shù)類型临庇、參數(shù)值都確定后也不一定會直接鎖定構(gòu)造函數(shù)反璃,不同構(gòu)造函數(shù)的參數(shù)為父子關(guān)系,所以Spring在最后又做了一次驗證假夺。
// 探測是否有不確定性的構(gòu)造函數(shù)存在淮蜈,例如不同構(gòu)造函數(shù)的參數(shù)為父子關(guān)系
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 如果它代表著當前最接近的匹配則選擇作為構(gòu)造函數(shù)
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
根據(jù)實例化策略以及得到的構(gòu)造函數(shù)及構(gòu)造函數(shù)參數(shù)實例化Bean
if (System.getSecurityManager() != null) {
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
}
}, beanFactory.getAccessControlContext());
}
else {
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
后面章節(jié)進行描述。
instantiateBean
不帶參數(shù)的構(gòu)造函數(shù)實例化過程
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
/**
* Instantiate the given bean using its default constructor.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return BeanWrapper for the new instance
*/
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
}, getAccessControlContext());
}
else {
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
}
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
實例化策略
其實已卷,經(jīng)過前面的分析梧田,我們已經(jīng)得到了足以實例化的所有相關(guān)信息,完全可以使用最簡單的反射方法直接反射來構(gòu)造實例對象侧蘸,但是Spring卻并沒有這么做裁眯。
SimpleInstantiationStrategy#instantiate
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
// 如果有需要覆蓋或者動態(tài)替換的方法則當然需要使用 cglib 進行動態(tài)代理,因為可以在
// 創(chuàng)建代理的同時將方法將動態(tài)方法織入類中闺魏,但是如果沒有需要動態(tài)改變的方法,為了
// 方便直接反射就可以了
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
CglibSubclassingInstantiationStrategy#instantiate
/**
* An inner class created for historical reasons to avoid external CGLIB dependency
* in Spring versions earlier than 3.2.
*/
private static class CglibSubclassCreator {
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
private final RootBeanDefinition beanDefinition;
private final BeanFactory owner;
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
this.beanDefinition = beanDefinition;
this.owner = owner;
}
/**
* Create a new instance of a dynamically generated subclass implementing the
* required lookups.
* @param ctor constructor to use. If this is {@code null}, use the
* no-arg constructor (no parameterization, or Setter Injection)
* @param args arguments to use for the constructor.
* Ignored if the {@code ctor} parameter is {@code null}.
* @return new instance of the dynamically generated subclass
*/
public Object instantiate(Constructor<?> ctor, Object... args) {
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
Object instance;
if (ctor == null) {
instance = BeanUtils.instantiateClass(subclass);
}
else {
try {
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
instance = enhancedSubclassConstructor.newInstance(args);
}
catch (Exception ex) {
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
}
}
// SPR-10785: set callbacks directly on the instance instead of in the
// enhanced class (via the Enhancer) in order to avoid memory leaks.
Factory factory = (Factory) instance;
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
return instance;
}
/**
* Create an enhanced subclass of the bean class for the provided bean
* definition, using CGLIB.
*/
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
if (this.owner instanceof ConfigurableBeanFactory) {
ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
}
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
enhancer.setCallbackTypes(CALLBACK_TYPES);
return enhancer.createClass();
}
}
記錄創(chuàng)建 bean 的 ObjectFactory
在 doCreate
函數(shù)中有這樣一段代碼:
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 4
// 是否需要提前曝光:單例 & 允許循環(huán)依賴 & 當前 bean 正在創(chuàng)建中俯画,檢測循環(huán)依賴
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 為了避免后期循環(huán)依賴析桥,可以在 bean 初始化完成前將創(chuàng)建實例的 ObjectFactory 加入工廠
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
// 對 bean 再一次依賴引用,主要應(yīng)用 SmartInstantiationAware BeanPostProcessor,
// 其中我們熟知的 AOP 就是在這里將 advice 動態(tài)織入 bean 中艰垂,若沒有直接返回 bean泡仗,不做任何處理
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
-
mbd.isSingleton
: 是否是單例
-
this.allowCircularReferences
: 是否允許循環(huán)依賴,很抱歉猜憎,并沒有找到在配置文件中如何配置娩怎,但是在 AbstractRefreshableApplicationContext 中提供了設(shè)置函數(shù),可以通過硬編碼的方式進行設(shè)置或者可以通過自定義命名空間進行配置胰柑,其中硬編碼的方式代碼如下:ClassPathXmlApplicationContext bf = new ClassPathXmlApplicationContext ("aspectTest.xml"); bf.setAllowBeanDefinitionOverriding(false);
-
isSingletonCurrentlyInCreation(beanName)
: 該bean是否在創(chuàng)建中截亦。在Spring中,會有個專門的屬性默認為DefaultSingletonBeanRegistry
的singletonsCurrentlyInCreation
來記錄bean的加載狀態(tài)柬讨,在bean開始創(chuàng)建前會將beanName記錄在屬性中崩瓤,在bean創(chuàng)建結(jié)束后會將 beanName 從屬性中移除。記錄狀態(tài)的點踩官,不同 scope 的位置不一樣却桶,以
singleton
為例,在singleton下記錄屬性的函數(shù)是在DefaultSingletonBeanRegistry
類的public Object getSingleton(String beanName, ObjectFactory singletonFacotry)
函數(shù)的beforeSingletonCreation(beanName)
和afterSingletonCreation(beanName)
中,在這兩段函數(shù)中分別是this.singletonsCurrentlyInCreation.add(beanName)
與this.singletonsCurrentlyInCreation.remove(beanName)
來進行狀態(tài)的記錄與移除颖系。
屬性注入
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw BeanWrapper with bean instance
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
// 沒有可填充的屬性
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 給 InstantiationAwareBeanPostprocessors 最優(yōu)一次機會在屬性設(shè)置前來改變 bean
// 如:可以用來支持屬性注入的類型
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) { // 1
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 返回值為是否繼續(xù)填充 bean
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 如果后處理器發(fā)出停止填充命令則終止后續(xù)的運行
if (!continueWithPropertyPopulation) {
return;
}
// 2
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根據(jù)名稱自動注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根據(jù)類型自動注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 后處理器已經(jīng)初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 需要依賴檢查
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) { // 3
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 對所有需要依賴檢查的屬性進行后處理
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
// 依賴檢查嗅剖,對應(yīng) depends-on 屬性, 3.0 已經(jīng)棄用此屬性
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
// 將屬性應(yīng)用到 bean 中
applyPropertyValues(beanName, mbd, bw, pvs); // 4
}
-
InstantiationAwareBeanPostProcessor
處理器的postProcessAfterInstantiation
函數(shù)的應(yīng)用嘁扼,此函數(shù)可以控制程序是否繼續(xù)進行屬性填充信粮。 - 根據(jù)注入類型(byName/byType),提取依賴的 bean偷拔,并統(tǒng)一存入
PropertyValues
中蒋院。 - 應(yīng)用
InstantiationAwareBeanPostProcessor
處理器的postProcessPropertyValues
方法,對屬性獲取完畢填充前對屬性的再次處理莲绰,典型應(yīng)用是RequiredAnnotationBeanPostProcessor
類中對屬性的驗證欺旧。 - 將所有
PropertyValues
中的屬性填充至BeanWrapper
中。
在上面的步驟中有幾個地方是我們比較感興趣的蛤签,它們分別是依賴注入( autowireByName
/autowireByType
)以及屬性填充辞友,那么,接下來進一步分析這幾個功能的實現(xiàn)細節(jié)震肮。
autowireByName
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 尋找 bw 中需要依賴注入的屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 遞歸初始化相關(guān)的 bean
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
// 注冊依賴
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
autowireByType
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
// 尋找 bw 中需要依賴注入的屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
if (Object.class != pd.getPropertyType()) {
// 探測指定屬性的 set 方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
// 解析指定 beanName 的屬性所匹配的值称龙,并把解析到的屬性名稱存儲在
// autowireBeanNames 中,當屬性存在多個封裝 bean 時戳晌,如:
// @Autowired private List<A> aList; 將會找到所有匹配 A 類型
// 的 bean 并將其注入
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
// 注冊依賴
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
現(xiàn)根據(jù)名稱自動匹配的第一步就是尋找 bw
中需要依賴注入的屬性鲫尊,同樣對于根據(jù)類型自動匹配的實現(xiàn)來講第一步也是尋找bw
中需要依賴注入的屬性,然后遍歷這些屬性并尋找類型匹配的 bean沦偎,其中最復(fù)雜的就是尋找類型匹配的 bean疫向。
DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (javaUtilOptionalClass == descriptor.getDependencyType()) {
return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
// ObjectFactory 類注入的特殊處理
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
// javaxInjectProviderClass 類注入的特殊處理
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 通用邏輯處理
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
// 用于支持 Spring 中的注解 @Value
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 根據(jù)屬性類型找到 beanFactory 中所有類型的匹配 bean,
// 返回值的構(gòu)成為: key: 匹配的 beanName, value: beanName 對應(yīng)的實例化后的 bean(通過 getBean(beanName) 返回)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 如果 autowire 的 require 屬性為 true 而找到的匹配項卻為空則只能拋出異常
if (descriptor.isRequired()) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
return (instanceCandidate instanceof Class ?
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
applyPropertyValues
程序運行到這里豪嚎,已經(jīng)完成了對所有注入屬性的獲取搔驼,但是獲取的屬性是以PropertyValues
形式存在的,還并沒有應(yīng)用到已經(jīng)實例化的bean中侈询,這一工作是在applyPropertyValues
中舌涨。
/**
* Apply the given property values, resolving any runtime references
* to other beans in this bean factory. Must use deep copy, so we
* don't permanently modify this property.
* @param beanName the bean name passed for better exception information
* @param mbd the merged bean definition
* @param bw the BeanWrapper wrapping the target object
* @param pvs the new property values
*/
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (System.getSecurityManager() != null) {
if (bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
// 如果 mpvs 中的值已經(jīng)被轉(zhuǎn)換為對應(yīng)的類型那么可以直接設(shè)置到 beanWapper 中
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
// 如果 pvs 并不是使用 MutablePropertyValues 封裝的類型,那么直接使用原始的屬性獲取方法
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// 獲取對應(yīng)的解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
boolean resolveNecessary = false;
// 遍歷屬性扔字,將屬性轉(zhuǎn)換為對應(yīng)類的對應(yīng)屬性的類型
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
初始化 bean
大家應(yīng)該記得在 bean 配置時 bean 中有一個init-method
的屬性囊嘉,這個屬性的作用是在 bean 實例化前調(diào)用init-method
指定的方法來根據(jù)用戶業(yè)務(wù)進行相應(yīng)的實例化。我們現(xiàn)在就已經(jīng)進入這個方法了革为,首先看一下這個方法的執(zhí)行位置哗伯,Spring中程序已經(jīng)執(zhí)行過bean的實例化,并且進行了屬性的填充篷角,而就在這時將會調(diào)用用戶設(shè)定的初始化方法焊刹。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 對特殊的 bean 處理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 應(yīng)用后處理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 激活用戶自定義的 init 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 后處理器應(yīng)用
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
激活 Aware 方法
Spring 中提供一些 Aware 相關(guān)接口虐块,比如 BeanFactoryAware
俩滥、ApplicationContextAware
、ResourceLoaderAware
贺奠、ServletContextAware
等霜旧,實現(xiàn)這些 Aware 接口的 bean 在被初始之后,可以取得一些相對應(yīng)的資源儡率,例如實現(xiàn)BeanFactoryAware
的 bean 在初始后挂据, Spring 容器將會注入 BeanFactory
的實例,而實現(xiàn)ApplicationContextAware
的bean儿普,在bean被初始后崎逃,將會被注入ApplicationContext
的實例等。
Aware 的使用
-
定義 bean
public class Hello { public void say() { System.out.println("hello"); } }
-
定義
BeanFactoryAware
類型的 beanpublic class TestAware implements BeanFactoryAware { private BeanFactory beanFactory; // 聲明 bean 的時候 Spring 會自動注入 BeanFactory @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } public void testAware() { // 通過 hello 這個 bean id 從 beanFactory 獲取實例 Hello hello = (Hello) beanFactory.getBean("hello"); hello.say(); } }
-
測試
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("testAware.xml"); TestAware testAware = (TestAware) ctx.getBean("testAware"); testAware.testAware(); } /** hello **/
invokeAwareMethods
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
處理器的應(yīng)用
BeanPostProcessor
相信大家都不陌生眉孩,這是 Spring 中開放式架構(gòu)中一個必不可少的亮點个绍,給用戶充足的權(quán)限去更改或者擴展 Spring ,而除了 BeanPostProcessor
外還有很多其他的 PostProcessor
浪汪,當然大部分都是以此為基礎(chǔ)巴柿,繼承自 BeanPostProcessor
。BeanPostProcessor
的使用位置就是這里死遭,在調(diào)用客戶自定義初始化方法前以及調(diào)用自定義初始化方法后分別會調(diào)用 BeanPostProcessor
的 postProcessBeforeInitialization
和postProcessAfterInitialization
方法广恢,使用戶可以根據(jù)自己的業(yè)務(wù)需求進行響應(yīng)的處理。
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
激活自定義的 init 方法
客戶定制的初始化方法除了我們熟知的使用配置init-method
外呀潭,還有使自定義的 bean 實現(xiàn)InitializingBean
接口钉迷,并在afterPropertiesSet
中實現(xiàn)自己的初始化業(yè)務(wù)邏輯。
init-method
與afterPropertiesSet
都是在初始化 bean 時執(zhí)行蜗侈,執(zhí)行順序是afterPropertiesSet
先執(zhí)行篷牌,而init-method
后執(zhí)行睡蟋。
在invokeInitMethods
方法中就實現(xiàn)了這兩個步驟的初始化方法調(diào)用踏幻。
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
// 首先會檢查是否是 InitializingBean,如果是的話需要調(diào)用 afterPropertiesSet 方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 屬性初始化后的處理
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 調(diào)用自定義初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
注冊 DisposableBean
Spring 中不但提供了對于初始化方法的擴展入口戳杀,同樣也提供了銷毀方法的擴展入口该面,對于銷毀方法的擴展,除了我們熟知的配置屬性destroy-method
方法外信卡,用戶還可以注冊后處理器DestructionAwareBeanPostProcessor
來統(tǒng)一處理bean的銷毀方法隔缀,代碼如下(doCreateBean
中):
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
// 單例模式下注冊需要銷毀的 bean,此方法中會處理實現(xiàn) DisposableBean 的 bean傍菇,
// 并且堆所有的 bean 使用 DestructionAwareBeanPostProcessors 處理
// DisposableBean DestructionAwareBeanPostProcessors
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
// 自定義 scope 的處理
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}