一、Spring框架設計
Spring framework 6大模組
1.1 Spring AOP
AOP: 面向切面程式設計
Spring 早期版本的核心功能,管理物件宣告週期和物件裝配
為了實現管理和裝配,一個自然的想法就是,加一箇中間層代理(位元組碼增強)來實現所有物件的託管
IoC:控制反轉
IoC是一個寬泛的概念,而DI(依賴注入)是其中的一種實現方式。
從物件A直接引入和操作物件B,變成物件A只需要依賴一個介面IB,系統啟動和裝配階段,把IB介面的例項物件注入到物件A,這樣A就不需要依賴一個IB介面的具體實現。
從而達到修改配置檔案,就可以在執行時替換成注入IB介面的其他實現類的一個物件例項。
思考:Spring怎麼解決迴圈依賴?
當例項A依賴B,例項B依賴A時。就構成了迴圈依賴。Spring解決的思路就是先構造一個"早期"物件,物件的屬性還沒填充,然後將這個早期物件注入容器。讓B完成例項化,此時A就能獲取到B的引用,完成了例項化。
具體實現是通過Spring的三級快取。
什麼型別的迴圈依賴Spring無法處理?
答:雙方都是建構函式注入或主bean物件(Spring啟動中先載入的物件)使用建構函式注入。
構造器注入和setter注入在建立bean時候的區別
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
///隱藏無用程式碼
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
//獲取構造器注入
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
//如果ctors不為空,就是構造器注入
if (ctors != null) {
return
//需要去建立構造器裡依賴的bean,此時還沒例項化出物件來放入三級快取
autowireConstructor(beanName, mbd, ctors, null);
}
//不是構造器注入,就可以例項化出一個bean來,並放入三級快取裡面了。
return instantiateBean(beanName, mbd);
}
Spring AOP的實現方式:
動態代理
介面型別,預設使用JDK動態代理。非介面型別預設使用CGlib。
如果介面型別想改為用CBlib動態代理:
spring xml:
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"/>
spring boot 配置檔案:
# 增加@EnableAspectJAutoProxy
spring.aop.auto=true
# 開啟CGLIB代理
spring.aop.proxy-target-class=true
位元組碼增強
1.2 Spring Bean
Bean的載入過程:
- 建立物件
- 屬性賦值
- 初始化
- 登出介面註冊
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 1. 例項化bean
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
/**
省略部分程式碼
**/
// Initialize the bean instance.
Object exposedObject = bean;
try {
//2.屬性賦值
populateBean(beanName, mbd, instanceWrapper);
//3.初始化
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);
}
}
/**
省略部分程式碼
**/
// 4.銷燬的回撥方法
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
Bean的初始化過程:
- 檢查Aware裝配
- BeanPostProcessors前置處理
- init方法
- BeanPostProcessors後置處理
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//1.檢查Aware介面並設定相關依賴
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//2.BeanPostProcessor前置處理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//若有init方法,則執行
//若實現了InitializingBean介面,則執行
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()) {
//BeanPostProcessor後置方法處理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}