1. 程式人生 > 其它 >第五週 Spring框架

第五週 Spring框架

一、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的載入過程:

  1. 建立物件
  2. 屬性賦值
  3. 初始化
  4. 登出介面註冊
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的初始化過程:

  1. 檢查Aware裝配
  2. BeanPostProcessors前置處理
  3. init方法
  4. 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;
	}