到目前為止,我們知道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
,一個是在初始化完之後呼叫,一個是容器銷燬時呼叫。
未完待續.....