天天看點

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

目錄

4.7.1 Spring

4.7.1.1 Spring子產品

4.7.1.1.1 資料子產品

4.7.1.1.2 Web子產品

4.7.1.1.3 切面子產品

4.7.1.1.4 工具子產品

4.7.1.1.5 消息子產品

4.7.1.1.6 核心子產品

4.7.1.1.7 測試子產品

4.7.2 SpringIOC架構原理

4.7.2.1 Bean初始化狀态

4.7.2.2 概念bean → 定義bean

4.7.2.3 生産bean

4.7.2.4 執行個體化bean

4.7.2.4.1 反射

4.7.2.4.2 工廠方法

4.7.2.4.3 工廠類

4.7.2.5 屬性注入

4.7.2.5.1 循環依賴

4.7.2.6 初始化

4.7.2.6.1 初始化方法

4.7.2.6.2 aware擴充接口

4.7.2.7 建立Bean

4.7.2.8 擴充接口

4.7.2.8.1 BeanFactoryPostProcessor接口

4.7.2.8.2 BeanDefinitionRegistryPostProcessor

4.7.2.8.3 BeanPostProcessor

4.7.3 Bean生命周期

4.7.3.1 簡化版本

4.7.3.2 詳細版本

4.7.3.3 循環依賴

4.7.3.3.1 循環依賴問題

4.7.3.3.2 解決方案:三級緩存

4.7.3.3.3 流程

4.7.4 AOP

4.7.1 Spring

Spring是什麼?

  • 架構:友善開發,整合其他架構
  • 容器:管理bean
  • 生态:目前主流的Java開發,都會用到Java全家桶。Springboot、Springcloud等架構都是對Spring的擴充實作。

4.7.1.1 Spring子產品

Spring 由七大子產品組成,分别是

  • 資料子產品(Data Access / Integration)
  • Web子產品
  • 切面子產品(Aop,Aspects)
  • 工具子產品(Instrumentation)
  • 消息子產品
  • 核心子產品
  • 測試子產品
4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

Spring子產品

4.7.1.1.1 資料子產品

資料通路與內建子產品,分為以下小子產品:

  • JDBC

     (Java Database Connectivity),Java資料庫連接配接
  • ORM

     (Object Relational Mapping), 對象關系映射
  • OXM

     (Object XML Mapping), 對象XML映射
  • JMS

     (Java Message Service),Java消息服務
  • Transactions

     ,事務

4.7.1.1.2 Web子產品

Web有以下小子產品:

  • Web
  • WebMVC
  • WebSocket
  • WebFlux

Web 子產品:提供了核心部分,如 編解碼,過濾器,序列化,國際化,跨域,轉換器,用戶端和服務端等。

WebMVC 子產品:即我們平時用的 

SpringMVC

WebSocket 子產品: 用來支援這個 全雙工通信

WebFlux子產品: 就是這個響應式Web程式設計子產品

4.7.1.1.3 切面子產品

包括AOP、Aspect兩個子產品。

AOP:基于代理的 Aop 架構

Aspect:定義了五種類型的切面

  • beans.factory.aspectj
  • cache.aspectj
  • context.annotation.aspectj
  • scheduling.aspectj
  • transaction.aspectj

4.7.1.1.4 工具子產品

 Instrumentation , 這個是 Java 的一個接口,用于

  • 監控代理
  • 事件日志記錄
  • 代碼覆寫率

4.7.1.1.5 消息子產品

Spring-messaging

 子產品提供了一種基于 

WebSocket

 的 

STOMP

 協定實作

STOMP

 (Simple Text Oriented Messaging Protocol) 是一種 流文本定向消息協定,也是一種為MOM(Message Oriented Middleware,面向消息的中間件)設計的簡單文本協定

常見的這幾個MQ都支援該協定,比如 

RocketMQ

RabbitMQ

ActiveMQ。

待更新

Spring的這七大子產品你了解嗎? - 知乎

4.7.1.1.6 核心子產品

分為四個核心子產品:

  • Beans
  • Core
  • Context
  • Expression

該核心子產品為重點,

4.7.1.1.7 測試子產品

主要是測試用,如Junit等。

4.7.2 SpringIOC架構原理

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

IOC流程圖

4.7.2.1 Bean初始化狀态

我們可以将bean概念态、定義态、純靜态、成熟态

概念态:

定義态:bean的構造圖

純靜态:循環依賴中展現純靜态的作用

成熟态:最終在應用中使用的bean

其中在ApplicationContext()中隐藏了另外兩種狀态

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

4.7.2.2 概念bean → 定義bean

BeanDefinition是相當重要的 

BeanDefinition:封裝了bean的定義資訊,決定一個bean是怎麼生産的,一個bean對應一個BeanDefinition

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

那麼這個BeanDefinition是怎麼來的呢?

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

當我們new ApplicationContext時會傳入一個xml檔案。不同的sapring上下文會傳入不同的,讀取bean定義的過程是有些不同的,但也有相同的地方。

方式一:ClassPathXmlApplicationContext(xml);
方式二:AnnotationConfigApplicationContext(配置類);
           

無論是ClassPathXmlApplicationContext(xml)還是AnnotationConfigApplicationContext(配置類)都有一個統一的接口ApplicationContext,是以它們會将公共的部分抽取出來,我們來研究這些公共的部分。

雖然有不同的spring上下文,但是都是由BeanDefinitionReader接口讀取配置資訊

讀取之後怎麼解析注解呢?

用掃描器ClassPathBeanDefinitionScanner,比如,我們定義了

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

它會掃描包下的.class,裡面有component注解,将這個類注冊為BeanDefinition。由于每個類都會有BenaDefinition,是以用beanDefinitionMap容器儲存。

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

之後由registerBeanDefinition将BeanDefinition注冊到BeanDefinitionMap中

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

 之後就是生産bean了。

4.7.2.3 生産bean

 這裡涉及到很重要的知識點:BeanFactory接口

BeanFactory負責生産,在BeanFactory中提供了getBean方法用來生産bean。

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

提出一個小問題,這裡Spring容器調用的getBean和BeanFactory裡的getBean是同一個方法嗎?

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

答案:是同一個

我們進入applicationContext.getBean(),會發現這裡的getBean是門面方法,沒有具體,而是交給BeanFactory去生産。

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

 當已存在bean就直接傳回給spring,如果沒有就生産後傳回。

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

既然ApplicationContext和BeanFactory都可以擷取bean,也就是說二者均可作為容器去使用。

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

那麼既然都可以作為容器,為什麼不直接在spring中書寫BeanFactroy,非要再整個ApplicationContext的門面方法,不多此一舉麼?

看完上面的繼承圖,我們發現ApplicationContext實作了BeanFactroy,這就好比,我們要買車,我們可以選擇去4S店,也可以選擇直接去汽車工廠。ApplicationContext就好比4S店,4S店有很多的服務,我們隻需要提需求,4S店都能完成。BeanFactroy就是汽車工廠,工廠的職責就一個:生産汽車。基本上我們和4S店比較熟悉,打交道比較多,同樣我們開發人員和ApplicationContext打交道比較多。我們隻需要把配置給ApplicationContext,它就能初始化。

但是BeanFactroy不行,它隻實作了簡單工廠,功能單一化,隻能根據BeanDefinition去生産bean。

通過ApplicationContext,我們隻需要getBean(car),就可以得到我們想要的bean,但是,如果注釋了ApplicationContext,我們再直接用beanFactory.get(car),就會報錯BeanDefinitionException。

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

因為像xml、配置類的資訊,都是由ApplicationContext(Spring 上下文)幫我們做了,ApplicationContext調用了BeanFactory來生産bean。

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

但是對于BeanFactory,我們必須手動将BenaDefinition傳給BeanFactory,才能生産bean。

但是BeanFactory記憶體更小,可以用于嵌入式開發。

4.7.2.4 執行個體化bean

執行個體化bean的方式:

  1. 反射
  2. 工廠方法
  3. 工廠類:FactoryBean

4.7.2.4.1 反射

@Component

将類讀取到beanClass中,spring利用反射執行個體化bean

4.7.2.4.2 工廠方法

注解形式

public class StaticFactoryBean {

   @Bean

    public static UserService createUserService(){    

            return new UserServiceImpl();

    }

}

 會将被标注的方法讀取到factoryMethodName

xml形式

而<bean id="" factory-bean="StaticFactoryBean全限定名" factory-method=" UserService"/>

在factory-method=" "中指定一個工廠方法,且這個工廠方法是靜态的,會将方法讀取到factoryMethodName 

4.7.2.4.3 工廠類

注意FactoryBean本身也是一個bean

 類執行個體化FactoryBean接口,并重寫getObject()、getObjectType()

@Component
public class FactoryBean_test implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
//這個才是傳回的真正的bean
        return new User();
    }
 
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }

           

工廠方法基于方法,而工廠類基于類

4.7.2.5 屬性注入

4.7.2.5.1 循環依賴

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

4.7.2.6 初始化

4.7.2.6.1 初始化方法

屬性注入之後,進行初始化,初始化時會調用init_Method()

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

 除了init-Method()外

還可以用注解@PostConstruct聲明一個初始化方法

以及利用InitializingBean接口,實作一個InitializingBean,重寫afterPropertiesSet()

4.7.2.6.2 aware擴充接口

檢查aware接口設定相關依賴

在spring容器中,我們可以把對象按照使用者分為兩類:自定義對象、容器使用的對象

  • 自定義對象:就是我們開發人員定義的Student、Taecher等對象
  • 容器使用的對象:BeanPostProcessor、BeanFactory等,這些都是由容器自己建立、自己調用。

但是如果我們自定義對象需要使用、調用這些容器所使用的對象時,怎麼辦?

你可以把這些容器所使用的對象當成一個普通屬性,如果是屬性,我肯定要調用屬性的set方法,往裡面指派。但是,對象的建立都交由容器來管理了,set方法調用肯定還是由容器管理,而且容器又不知道什麼時候調用。

是以這裡設定了統一的入口——aware接口。

所有調用容器對象設定的地方都會實作aware接口,如BeanFactoryAware、BeanNameAware等。

總的來說就是通過aware的具體實作子類,我們可以設定bean的一系列操作。

4.7.2.7 建立Bean

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

  建立好的bean會放入Map(單例池/一級緩存)中

當context.getBean("bean的名字");時,會到一級緩存中查詢,有就傳回,沒有就生産。

4.7.2.8 擴充接口

4.7.2.8.1 BeanFactoryPostProcessor接口

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory BeanFactory) throws BeansException;
}
           

 BeanFactoryPostProcessor中的postProcessBeanFactory()方法,直接傳來一個

4.7.2.8.2 BeanDefinitionRegistryPostProcessor

源碼定義如下:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
           

BeanDefinitionRegistryPostProcessor的作用是注冊BeanDefinition,也就是注冊了Bean

Spring-MyBatis中的Mapper是接口,動态代理

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

4.7.2.8.3 BeanPostProcessor

 BeanPostProcessor(bean的後置處理器)主要用在初始化前後

BeanPostProcessor有很多子接口

4.7.3 Bean生命周期

4.7.3.1 簡化版本

1、執行個體化bean,當客戶向容器請求一個尚未初始化的bean時,容器就會調用doCreateBean()方法進行執行個體化,實際上就是利用反射來建立一個bean對象

2、當bean對象建立出來後就對bean對象進行屬性填充,也就是注入這個bean依賴的其他對象

3、屬性填充完成後,進行初始化bean操作

         a、執行Aware接口方法,Spring會檢查該bean對象是否實作了xxxAware接口,通過Aware類型的接口,我們可以拿到spring容器的一些資源,如實作了BeanNameAware接口就可以擷取BeanName等等

        b、執行BeanPostProcessor的前置處理方法postProcessBeforeInitialization(),對Bean進行一些自定義的前置處理

        c、判斷bean是否實作了InitialalizationBean接口,如果實作了,将會執行InitialalizationBean的afterPropertiesSet()初始化方法

        d、執行使用者自定義的初始化方法,如init-method等

        e、執行BeanPostProcessor的後置處理方法postProcessAfterInitialization()

4、銷毀

        a、首先判斷Bean是否實作了DestructionAwareBeanPostProcessor接口,如果實作了,則執行DestructionAwareBeanPostProcessor後置處理器的銷毀方法

        b、其次判斷Bean是否實作了DisposableBean接口,如果實作了就會調用其實作的destroy()方法

        c、最後判斷Bean是否配置了destroy-method方法,如果有就調用其配置的銷毀方法

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

4.7.3.2 詳細版本

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {

//bean
 protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
//如果緩存中不存在,則調用createBeanInstance建立一個BeanWrapper(bean的包裝類)
        if (instanceWrapper == null) {
//bean的執行個體化
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }
//初始化bean執行個體
 Object exposedObject = bean;

//----------------省略-----------
//屬性填充
            this.populateBean(beanName, mbd, instanceWrapper);
//初始化bean,如執行aware接口的子類,執行init-method方法,BeanPostProcesso後置增強等
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);


//銷毀不在AbstractAutowireCapableBeanFactory 類,在DisposableBeanAdapter類中


}
           

 initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
//先執行aware的子類
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            this.invokeAwareMethods(beanName, bean);
        }

          Object wrappedBean = bean;
            if (mbd == null || !mbd.isSynthetic()) {
//執行beanPostProcessor後置處理器的前置方法BeanPostProcessorsBeforeInitialization
                wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
            }
//中間執行init-method
        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }
//最後執行BeanPostProcessorsAfterInitialization
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

           

 invokeAwareMethods

private void invokeAwareMethods(String beanName, Object bean) {

        if (bean instanceof Aware) {
//如果bean實作了BeanNameAware,那bean内部可以擷取到beanName屬性
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware)bean).setBeanName(beanName);
            }
//其他同理
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = this.getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
                }
            }

            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware)bean).setBeanFactory(this);
            }
        }

    }
           

 invokeInitMethods

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
//InitialalizationBean接口,如果實作了,将會執行InitialalizationBean的afterPropertiesSet()初始化方法
        boolean isInitializingBean = bean instanceof InitializingBean;
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }

            if (System.getSecurityManager() != null) {
                try {
//執行afterPropertiesSet()
                    AccessController.doPrivileged(() -> {
                        ((InitializingBean)bean).afterPropertiesSet();
                        return null;
                    }, this.getAccessControlContext());
                } catch (PrivilegedActionException var6) {
                    throw var6.getException();
                }
            } else {
                ((InitializingBean)bean).afterPropertiesSet();
            }
        }
//使用者自定義的初始化方法
        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
//使用者自定義的方法
                this.invokeCustomInitMethod(beanName, bean, mbd);
            }
        }

    }
           

 DisposableBeanAdapter

//銷毀
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
 public void destroy() {
        if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
            Iterator var1 = this.beanPostProcessors.iterator();

            while(var1.hasNext()) {
//先檢視DestructionAwareBeanPostProcessor接口
                DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
//如果實作了,則執行DestructionAwareBeanPostProcessor後置處理器的銷毀方法
                processor.postProcessBeforeDestruction(this.bean, this.beanName);
            }
        }
//接着看是否實作了DisposableBean接口
              if (System.getSecurityManager() != null) {
                   AccessController.doPrivileged(() -> {
//如果實作了就調用接口的destroy方法
                       ((DisposableBean)this.bean).destroy();
                            
                }
              }
//最後判斷是否有使用者自定義的銷毀方法
           if (this.destroyMethod != null) {
            this.invokeCustomDestroyMethod(this.destroyMethod);
        } else if (this.destroyMethodName != null) {
            Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
            if (methodToInvoke != null) {
//調用使用者自定義的銷毀方法
                this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
            }
        }
}
           

11張流程圖搞定 Spring Bean 生命周期 - 知乎

4.7.3.3 循環依賴

4.7.3.3.1 循環依賴問題

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

當spring容器初始化時,如先執行個體化A,之後A注入B,會找spring要B,之後會對B進行執行個體化,調用getBean(b)。執行個體化後發現還需要注入A,又去調用getBean(a)方法,此時成環,稱為循環依賴

4.7.3.3.2 解決方案:三級緩存

singletonObject(一級緩存):存放執行個體化 -> 代理 -> 屬性注入 ->初始化後的對象
earlySingletonObjects(二級緩存):存放執行個體化 -> 代理 -> 屬性注入 ->初始化後的對象
singletonFactories(三級緩存):存放對象工廠,可以從對象工廠中拿到還未屬性注入的對象(對象工廠便于建立代理對象)

4.7.3.3.3 流程

首先注意bean的簡單流程

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

 當getBean(),擷取bean時,spring會先到一級緩存中找,沒有再去二級緩存,若二級緩存還沒有就會建立一個對應的工廠對象,從工廠對象中執行個體化bean

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

屬性注入後的bean,會被放入到二級緩存中,同時删除三級緩存中的工廠對象

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

 初始化後的bean會被存入一級緩存中,同時删除二級緩存中"半成品"bean

4.7 深入了解Spring4.7.1 Spring4.7.2 SpringIOC架構原理4.7.3 Bean生命周期4.7.4 AOP

4.7.3.3.4 深入了解循環依賴

我們知道一級緩存的問題在于他沒法去存儲半成品bean,也就是未完全初始化好的對象,那麼spring出現了二級緩存,來存儲半成品的bean(開始建立但是不完整的對象)。

首先我們執行個體化A,還沒有進行屬性填充的時候,就把A對象存儲到二級緩存。然後進行屬性填充,A去填充B,發現B沒有執行個體化,于是B同樣執行個體化後,把半成品對象放入到二級緩存中。B開始進行填充,發現一級緩存中沒有A,但二級緩存中有A。于是B從二級緩存中取出A,填充A後,B就是一個完整的對象。之後B被放入一級緩存中。同時删除二級緩存中的B。由于A發現一級緩存中已經有B。之後A也就完成了屬性填充。、

看似二級緩存就已經能解決問題,為什麼還有引入三級緩存?

原因就是spring的AOP機制所産生的代理對象問題

先來簡單了解AOP代理對象

//待更新

Spring的代理對象産生階段是在填充屬性後才進行的,通過BeanPostProcessor來實作。如果在屬性填充時就将代理對象生成放入二級緩存,那麼就與spring的生命周期相悖

是以引入三級緩存

首先我們還是進行執行個體化A對象,這個時候,我們要将A的ObjectFactory對象放入三級緩存中。同樣的繼續進行屬性填充,這個時候B還沒建立,于是去建立B。那麼去執行個體化B的過程中,我們也是一樣的,先把B的ObjectFactory放入三級緩存中。将B對象放入二級緩存中。繼續執行到B的屬性填充,去擷取A對象,而此時一級緩存中沒有A,因為A還沒有建立完成,我們則發現三級緩存中有A的ObjectFactory對象,那麼我們通過objectFactory對象擷取A的早期對象,然後将這個早期對象放入二級緩存中,同時删除三級緩存中的A,然後我們将A的引用給了B,那麼同樣的B對象這個時候也已經完整了。接下來我們再把B放入一級緩存中接下來從三級緩存中删除B。這時候B已經建立完成,A繼續執行b的屬性填充可以拿到B對象,這樣A也完成,最後我們把A對象也放入了一級緩存,删除掉二級緩存中的A。于是我們的循環依賴就此解決。

4.7.4 AOP

單例bean

Spring中的Bean對象預設是單例的,架構并沒有對Bean進行多線程封裝處理

單例bean是指IOC容器中就隻有這麼一個bean,是全局共享的。分為有狀态bean和無狀态bean。

有狀态的bean

就是有執行個體變量的對象,可以儲存資料(有狀态就是有資料存儲功能),是線程不安全的。每個使用者都有自己特有的執行個體,在使用者的生命周期中,bean儲存了使用者的資訊,即為“偶狀态”;一旦使用者衰亡(調用結束),bean的生命周期也随之結束。即每個使用者最初都會得到一個初始的bean。

無狀态的bean

就是沒有執行個體變量的對象,不能儲存資料,是不變類,是線程安全的。bean一旦執行個體化就被加進會話池中,各個使用者都可以共用。即使使用者已經消亡,bean的生命期也不一定結束,它可能依然存在于會話池中,供其他使用者調用。由于沒有特定的使用者,那麼也就不能保持某一使用者的狀态,是以叫無狀态bean。但無狀态會話bean 并非沒有狀态,如果它有自己的屬性(變量),那麼這些變量就會受到所有調用它的使用者的影響,這是在實際應用中必須注意的。

 執行個體變量

java類的成員變量有倆種:一種是被static關鍵字修飾的變量,叫類變量或者靜态變量;另一種沒有static修飾,為執行個體變量。

class Car{

private name;   //這就是執行個體變量

public void 方法(){};

}

當一個對象被執行個體化之後,每個執行個體變量的值就跟着确定;

執行個體變量在對象建立的時候建立,在對象被銷毀的時候銷毀;

如果Bean是有狀态的,那就需要開發人員自己來進行線程安全的保證,最簡單的辦法就是改變bean的作用域 把 "singleton"改為’‘protopyte’ 這樣每次請求Bean就相當于是 new Bean() 這樣就可以保證線程的安全了。

無狀态就是不會存儲資料,試想controller,service和dao本身并不是線程安全的,隻是調用裡面的方法,而且多線程調用一個執行個體的方法,會在記憶體中複制周遊,這是自己線程的工作記憶體,是最安全的。是以在進行使用的時候,不要在bean中聲明任何有狀态的執行個體變量或者類變量,如果必須如此,也推薦大家使用ThreadLocal把變量變成線程私有,如果bean的執行個體變量或者類變量需要在多個線程之間共享,那麼就隻能使用synchronized、lock、cas等這些實作線程同步的方法。但是一旦使用了synchronized、lock等線程同步方法,又會降低系統效率。

//待更新