到目前為止,我們知道Spring創建Bean物件有5中方法,分別是:
- 使用
FactoryBean的getObject方法創建 - 使用
BeanPostProcessor的子介面InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法創建 - 設定
BeanDefinition的Supplier屬性進行創建 - 設定
BeanDefinition的factory-method進行創建 - 使用全程序:
getBean-->doGetBean-->createBean-->doCreateBean反射進行創建
前面4中已經介紹,接下來介紹第5種,我們知道如果使用反射創建,那么必然要知道使用建構式進行實體化,因為使用建構式能夠將帶有引數的設定進去,
SmartInstantiationAwareBeanPostProcessor 介面
在前面講過InstantiationAwareBeanPostProcessor 是用來提前實體化物件的,而SmartInstantiationAwareBeanPostProcessor 是InstantiationAwareBeanPostProcessor 的子介面,他是用來干啥呢?
在createBeanInstance方法中的原始碼:
// 省略代碼....
// 明確構造器從BeanPostProcessor中,對應的是 AutowiredAnnotationBeanPostProcessor
// 他是 SmartInstantiationAwareBeanPostProcessor 的子類,使用determineCandidateConstructors進行
// 決議建構式
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 省略代碼....
點進去:
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 決定候選的建構式
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
可以看到這個介面是用來決議BeanClass的建構式的,SmartInstantiationAwareBeanPostProcessor的實作類AutowiredAnnotationBeanPostProcessor,這個類是用來決議確定合適的建構式,重點決議了@Autowired注解,并且還決議了@Value注解和@Lookup注解,
當決議出來建構式之后,那么就呼叫autowireConstructor方法進行實體化,決議時會new一個構造器決議器ConstructorResolver ,在決議factoryMehod時也是使用的這個類使用的是instantiateUsingFactoryMethod這個方法,并且決議factoryMethod更加復雜,需要判斷是否是靜態的工廠創建還是實體工廠創建,而自動裝配的構造決議相對來說簡單一些,使用autowireConstructor方法進行決議,
最終決議出構造方法和構造引數之后進行實體化:
// 使用合適的構造方法和構造引數進行實體化
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
實體化:
private Object instantiate(
String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
try {
// 獲取實體化策略,一般使用 CglibSubClassingInstantiationStrategy
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
this.beanFactory.getAccessControlContext());
}
else {
// 開始實體化
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {
if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
// 實體化類,反射呼叫
return BeanUtils.instantiateClass(ctor, args);
}
else {
// 如果方法被覆寫,lookup-method 和 replace-method
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}
如果前面的決議都沒有到Bean,那么就會使用無參建構式進行決議:
// 省略代碼....
// Preferred constructors for default construction?
// 首選的構造器為默認的創建方式,使用了@Primary注解的為首選的創建物件方式
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 呼叫無參建構式實體化物件
return instantiateBean(beanName, mbd);
實體化Bean:
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
// 實體化物件,使用反射進行創建
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
// 創建一個Bean的包裝器
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
// 初始化Bean的包裝器
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
這里可以看到前面使用factoryMethod 和autowireConstructor 決議建構式進行實體化還是使用無參建構式進行實體化都是將Bean進行了包裝,那這個包裝有啥作用呢?
BeanWrapper的作用
我們先來看下前面的方法是怎么創建BeanWrapper的:
factory-method 決議,ConstructorResolver#instantiateUsingFactoryMethod 方法:
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
// 創建一個Bean的包裝器
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// factoryBean
Object factoryBean;
// factory 工廠類
Class<?> factoryClass;
// 標識是否是靜態的工廠
boolean isStatic;
// 省略代碼....
}
SmartInstantiationAwareBeanPostProcessor子類AutowiredAnnotationBeanPostProcessor 決議出建構式,然后使用ConstructorResolver#autowireConstructor 執行:
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
// 創建一個包裝器
BeanWrapperImpl bw = new BeanWrapperImpl();
// 初始化包裝器
this.beanFactory.initBeanWrapper(bw);
// 建構式
Constructor<?> constructorToUse = null;
// 構造引數
ArgumentsHolder argsHolderToUse = null;
// 需要使用的構造引數
Object[] argsToUse = null;
// 明確的構造引數不為空,則賦值給將要執行實體化的構造引數
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
// 省略代碼....
}
最終都是會進行轉換服務ConversionService和PropertyEditorRegistry的注冊,一個是用來進行屬性型別轉換的,一個是用來屬性值決議的:
protected void initBeanWrapper(BeanWrapper bw) {
// 獲取轉換服務放到bean的包裝器中
bw.setConversionService(getConversionService());
// 注冊定制的屬性編輯器
registerCustomEditors(bw);
}
在前面的文章中,介紹了這兩個如何使用,而且還自定義了屬性編輯器和型別轉換,需要的小伙伴可以去看看:
https://www.cnblogs.com/redwinter/p/16167214.html 和 https://www.cnblogs.com/redwinter/p/16241328.html
到這里Bean的實體化就完成了,接著往下看原始碼:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
// 從快取中獲取FactoryBean的Bean物件
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 實體化物件
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 從包裝器中獲取Bean物件
Object bean = instanceWrapper.getWrappedInstance();
// 從包裝器中獲取Bean型別
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 合并Bean
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
}
點進去:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
// 執行合并BeanDefinition
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
可以看到這里出現了一個介面MergedBeanDefinitionPostProcessor,這個介面也是BeanPostProcessor的子介面,那他到底是干啥用的呢?
MergedBeanDefinitionPostProcessor 介面
點擊發現這個介面的實作類全是跟注解相關的,而最重要的是CommonAnnotationBeanPostProcessor實作類,在建構式中設定了兩個注解:@PostConstruct 和 @PreDestroy ,一個是在初始化完之后呼叫,一個是容器銷毀時呼叫,
未完待續.....
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/473416.html
標籤:Java
上一篇:java中如何生成UUID呢?
下一篇:python常用內置函式和關鍵字
