日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

大綱

  • 容器的基本用法
  • spring啟動過程分析(spring生命周期)
  • bean 的生命周期
  • IOC核心類總結
  • 常用擴展點

容器的基本用法

spring 是企業級開發框架, 主要功能有 IOC,AOP,Web,ORM等

spring IOC專門用于管理bean對象, 管理對象的創建,屬性注入等

spring AOP 給予動態代理,實現了切面編程,動態實現對象功能擴展

 

spring 與其他框架整合,通過 spring 提供的擴展點,把其他框架的對象交給 spring 管理, 對象交給 spring 管理是想要避免手動創建對象,也可以通過@Autowired 等注解實現屬性注入,讓我們使用對象起來更加方便

  • spring xml 方式配置示例
//1 xml 方式配置spring  bean<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://www.springframework.org/schema/beans        https://www.springframework.org/schema/beans/spring-beans.xsd">    <!-- 配置spring  bean -->    <bean id="petStore" class="cn.JAVAbus.PetStoreService.class">   </bean></beans>//2  初始化 IOC容器ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");PetStoreService service = context.getBean("petStore", PetStoreService.class);

spring啟動過程分析(spring生命周期)

spring生命周期與bean生命周期

  • spring啟動過程描述

1 BeanDefinition 解析注冊

->多種配置方式配置Bean(xml,注解Component,java config)

->各種配置抽象為Resource資源

->通過BeanDefinitionReader 解析BeanDefinition 注冊到 BeanDefinitionRegistry

 

2 PostProcessor 各種處理器注冊調用

->獲取BeanFactory

->注冊和調用BeanFactoryPostProcessor(bean工廠后置處理器)

->注冊BeanFactoryPostProcessors

 

3 bean 生命周期處理

->實例化對象

->依賴注入

->bean 初始化

-> 存放到SpringContext容器

  • 以AbstractApplicationContext中的refresh()方法為起點進行源碼分析
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {  this(); //創建BeanDefinitionReader,BeanDefinitionScanner對象  //BeanDefinition解析和注冊 (DefaultListableBeanFactory.beanDefinitionMap)  register(componentClasses);  refresh();}public void refresh() throws BeansException, IllegalStateException {  synchronized(this.startupShutdownMonitor) {    StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");    //記錄容器開始時間startupDate,設置活躍狀態為true,設置environment對象    this.prepareRefresh();    //1 創建beanFactory實例對象, 一般是DefaultListableBeanFactory    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();    // Prepare the bean factory for use in this context.    prepareBeanFactory(beanFactory);    try {      // 空實現留給子類擴展 Allows post-processing of the bean factory in context subclasses.      postProcessBeanFactory(beanFactory);      StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");      // Invoke factory processors registered as beans in the context.      //2 按照順序注冊BeanFactoryPostProcessors,并且按照順序調用      invokeBeanFactoryPostProcessors(beanFactory);      // Register bean processors that intercept bean creation.      //3  按照順序注冊BeanPostProcessors      registerBeanPostProcessors(beanFactory);      beanPostProcess.end();      // 注冊國際化相關內容 Initialize message source for this context.      initMessageSource();      // 初始化事件廣播 Initialize event multicaster for this context.      initApplicationEventMulticaster();      // 空實現留給子類擴展 Initialize other special beans in specific context subclasses.      onRefresh();      // 注冊監聽器并且廣播早期事件 Check for listener beans and register them.      registerListeners();      // Instantiate all remaining (non-lazy-init) singletons.      //4 調用getBean()方法對非延遲加載的bean進行實例化 (最重要,涉及bean生命周期)      finishBeanFactoryInitialization(beanFactory);      // Last step: publish corresponding event.      finishRefresh();    }  }}

spring bean的生命周期

Spring中每個Bean的生命周期如下:

圖片來源于網絡

  • spring bean 生命周期 (Bean 解析和注冊)

實例化 -> 屬性賦值 -> 初始化 -> 銷毀

實例化 Instantiation

屬性賦值 Populate

初始化 Initialization

銷毀 Destruction

 

class

->構造器->反射創建對象

-> 依賴注入(@Autowired)

-> 初始化前(@PostConstruct)->初始化(InitializingBean)->初始化后(AOP)

-> 代理對象->bean

  • spring bean生命周期代碼入口 finishBeanFactoryInitialization(beanFactory)
//真正邏輯在 AbstractAutowireCapableBeanFactory.doCreateBean()finishBeanFactoryInitialization()DefaultListableBeanFactory#preInstantiateSingletons()getBean(beanName)AbstractBeanFactory.doGetBean()AbstractAutowireCapableBeanFactory#createBean()//1 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); //2 對象實例化 AbstractAutowireCapableBeanFactory.doCreateBean() Object beanInstance = doCreateBean(beanName, mbdToUse, args);BeanWrapper instanceWrapper = null;//doCreateBean-1 通過反射創建對象實例 (調用構造器創建對象)instanceWrapper = createBeanInstance(beanName, mbd, args);//doCreateBean-2 給后置BDpost-processors 一個修改 BeanDefinition的機會applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);    //doCreateBean-3 通過提前暴露一個單例工廠方法,從而使得其他 bean 能夠引用到該 bean (解決單例 bean循環依賴)addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));//doCreateBean-4 DI 依賴注入 (對象屬性初始化,各個屬性值注入,其中可能注入其他 bean 的屬性,這時候會遞歸初始化依賴 bean)populateBean(beanName, mbd, instanceWrapper);//doCreateBean-5 調用初始化方法,比如 init-methodexposedObject = initializeBean(beanName, exposedObject, mbd);//initializeBean-1 調用 Aware接口實現類invokeAwareMethods(beanName, bean);//initializeBean-2 bean前置處理 beanProcessor.postProcessBeforeInitialization();wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//initializeBean-3 調用初始化方法((InitializingBean) bean).afterPropertiesSet();invokeInitMethods(beanName, wrappedBean, mbd);//initializeBean-4 bean后置處理 beanProcessor.postProcessAfterInitialization()wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);return exposedObject;//3return beanInstance;  //然后回到AbstractBeanFactory.doGetBean(),執行getSingleton(),注冊 bean到容器sharedInstance = getSingleton(beanName, () -> {//todo  2.2 創建 單實例bean (ctrl+T)return createBean(beanName, mbd, args);}     
  • spring bean 生命周期核心代碼邏輯
// AbstractBeanFactory.doGetBean()protected <T> T doGetBean(final String name, ...) {  // 1 提取對應的 beanName (傳入的 name 可能是別名,FactoryBean(name="&aa"))  final String beanName = transformedBeanName(name);  Object bean;  // 2 嘗試直接從緩存獲取,或者singletonFactories 中的 objectFactory中獲取  Object sharedInstance = getSingleton(beanName);  if (sharedInstance != null && args == null) {    //該條件一般為二次獲取 bean 才會進入  }else {    //lambda 方式調用 DefaultSingletonBeanRegistry.getSingleton(beanName, ObjectFactory<?>)    //獲取createBean()創建的bean對象后,走getSingleton()邏輯添加bean 到bean容器(DefaultSingletonBeanRegistry.singletonObjects    sharedInstance = getSingleton(beanName, () -> {      //todo  2.2 調用createBean()方法創建對象      return createBean(beanName, mbd, args);    }    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  }}//...return (T) bean;}  //AbstractAutowireCapableBeanFactory.doCreateBean()//spring bean 生命周期核心代碼邏輯 (bean 實例化,依賴注入,以及初始化)protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args){  // Instantiate the bean. (裝飾模式)  BeanWrapper instanceWrapper = null;  if (instanceWrapper == null) {    //todo 1 根據指定的 bean 使用對應的策略來創建 bean,如:工廠方法,構造函數注入,簡單初始化    instanceWrapper = createBeanInstance(beanName, mbd, args);  }  // Initialize the bean instance.  try {    //todo 2 DI 依賴注入 (對象屬性初始化,各個屬性值注入,其中可能注入其他 bean 的屬性,這時候會遞歸初始化依賴 bean)    populateBean(beanName, mbd, instanceWrapper);    //todo 3 調用初始化方法,比如 init-method    exposedObject = initializeBean(beanName, exposedObject, mbd);  }  // ...Register bean as disposable.   return exposedObject;} 

Bean生命周期-常用擴展點

  • 第一大類:容器級生命周期接口方法(影響多個Bean的接口)

容器級生命周期接口方法:包含了
InstantiationAwareBeanPostProcessor和BeanProcessor這兩個接口實現,稱他們的實現類為“后處理器”。

實現了這些接口的Bean會切入到多個Bean的生命周期中。因此,這些接口的功能非常強大,Spring內部擴展也經常使用這些接口,例如自動注入以及AOP的實現都和他們有關。

 

1 BeanPostProcessor 作用于初始化階段的前后

2
InstantiationAwareBeanPostProcessor 作用于實例化階段的前后,

 

這兩兄弟可能是Spring擴展中最重要的兩個接口!

工廠后處理器接口方法:包含了AspectJWeavingEnabler、
ConfigurationClassPostProcessor、CustomAutowreConfigure等非常有用的工廠后處理器接口的方法,會在應用上下文裝配配置文件后立即調用。

  • 第二大類:Bean級別生命周期接口方法(每個 bean調用一次的接口)

1 Aware類型的接口

2 Bean生命周期接口 包含了BeanNameAware、BeanFactoryAware、initialzingBean和DiposableBean這些接口的方法

3 Bean的自身方法: 這個包括了init-method和destory-method方法

 

Aware類型的接口的作用就是讓我們能夠拿到Spring容器中的一些資源。

基本都能夠見名知意,Aware之前的名字就是可以拿到什么資源,例如BeanNameAware可以拿到BeanName,以此類推。

調用時機需要注意:所有的Aware方法都是在初始化階段之前調用的!

  • 各個接口調用時機演示
//1 BeanFactoryPostProcessor 工廠后處理器接口@Componentpublic class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {  public CustomBeanFactoryPostProcessor() {    System.out.println("==[BeanFactoryPostProcessor 接口]調用了 CustomBeanFactoryPostProcessor 構造器");  }  @Override  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {    System.out.println("==[BeanFactoryPostProcessor 接口]調用了 CustomBeanFactoryPostProcessor.postProcessBeanFactory() 修改bean定義");    //BeanDefinition beanDefinition = beanFactory.getBeanDefinition("person");    //beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);    beanFactory.registerSingleton("newobjr",new Object());  }}// 2 BeanPostProcessor bean處理器  @Componentpublic class CustomBeanPostProcessor implements BeanPostProcessor {  public CustomBeanPostProcessor() {    System.out.println("==[BeanPostProcessor 接口]調用了 CustomBeanPostProcessor 構造器");  }  @Override  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {    System.out.println("==4 [BeanPostProcessor 接口]調用了 "+beanName+".postProcessBeforeInitialization()");    return bean;  }@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  System.out.println("==6 [BeanPostProcessor 接口]調用了 "+beanName+".postProcessAfterInitialization()");  return bean;}}// 3Bean級別生命周期接口方法  @Componentpublic class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {  public Person() {    System.out.println("==1 [Person]調用了構造器,進行對象實例化");  }  @Override  public void setBeanName(String s) {    System.out.println("==2 [BeanNameAware 接口]調用了 BeanNameAware.setBeanName()");  }  @Override  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {    System.out.println("==3 [BeanFactoryAware 接口]調用了 BeanFactoryAware.setBeanFactory()");  }//==4 BeanPostProcessor.postProcessBeforeInitialization()...@PostConstruct//@PostConstruct是一種 BeanPostProcessorpublic void demo() {  System.out.println("==5.1 [@PostConstruct]調用了 Person.demo()");}@Overridepublic void afterPropertiesSet() throws Exception {  System.out.println("==5.2 [InitializingBean 接口]調用了 InitializingBean.afterPropertiesSet()");}//==6 BeanPostProcessor.postProcessAfterInitialization()...@Overridepublic void destroy() throws Exception {  System.out.println("==7 [DisposableBean 接口]調用了 DisposableBean.destroy()");}}  @ComponentScan(basePackages = "spring")public class SpringTest {  public static void main(String[] args) {    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);    System.out.println("spring 容器初始化成功");    Person person1 = context.getBean(Person.class);    //Person person2 = context.getBean(Person.class);    //boolean r = person1 == person2;    //System.out.println("person1 == person2 結果為:" + r); //結果為:false, 在BeanFactoryPostProcessor 中修改了bean scope    context.registerShutdownHook();    System.out.println("main結束");  }}
==[BeanFactoryPostProcessor 接口]調用了 CustomBeanFactoryPostProcessor 構造器==[BeanFactoryPostProcessor 接口]調用了 CustomBeanFactoryPostProcessor.postProcessBeanFactory() 修改bean定義==[BeanPostProcessor 接口]調用了 CustomBeanPostProcessor 構造器==4 [BeanPostProcessor 接口]調用了 springTest.postProcessBeforeInitialization()==6 [BeanPostProcessor 接口]調用了 springTest.postProcessAfterInitialization()//通過以下輸出可以觀察到person對象,生命周期接口方法調用順序==1 [Person]調用了構造器,進行對象實例化==2 [BeanNameAware 接口]調用了 BeanNameAware.setBeanName()==3 [BeanFactoryAware 接口]調用了 BeanFactoryAware.setBeanFactory()==4 [BeanPostProcessor 接口]調用了 person.postProcessBeforeInitialization()==5.1 [@PostConstruct]調用了 Person.demo()==5.2 [InitializingBean 接口]調用了 InitializingBean.afterPropertiesSet()==6 [BeanPostProcessor 接口]調用了 person.postProcessAfterInitialization()spring 容器初始化成功person1 == person2 結果為:truemain結束==7 [DisposableBean 接口]調用了 DisposableBean.destroy()

Spring IOC核心類總結

1 BeanDefinition 用于封裝 spring bean 的配置信息

2 BeanDefinitionRegistry 用于存放解析后的BeanDefinition對象,spring 提供了擴展機制,允許用戶在 spring 框架啟動時動態的往BeanDefinitionRegistry容器中注冊對象

 

3 BeanFactory 是 Spring 的Bean 工廠,負責 Bean 創建和屬性注入(
DefaultListableBeanFactory)

4 BeanFactoryPostProcessor ,BeanFactory的后置處理器; 是 spring 提供的擴展機制;

允許在所有 BeanDefinition配置信息解析完成后,修改 BeanFactory(Bean工廠)信息.例如向BeanDefinitionRegistry注冊BeanDefinition對象

在BeanFactory創建完成后會調用BeanFactoryPostProcessor實現類的 postProcessBeanFactory() 方法

 

5
ImportBeanDefinitionRegistrar接口作用于 Spring 解析 Bean 的配置階段,當解析@Configuration 注解時調用. 需要配合@Import 注解使用

 

6 BeanPostProcessor 是Bean的后置處理器.在 Bean 初始化方法(init-method 屬性指定的方法或者 afterPropertiesSet()方法)調用前后,會執行 BeanPostProcessor的攔截邏輯

 

7
ClassPathBeanDefinitionScanner 是BeanDefinition掃描器,能夠對象指定包下的 Class 進行掃描,將 Class 轉換為BeanDefinition對象注冊到BeanDefinitionRegistry 容器中

 

8 FactoryBean 是 Spring 中的工廠 bean,通常用于處理 spring 中配置較為復雜或者由動態代理生成的 Bean 實例.

實現了該接口的 Bean 不能作為普通的 Spring bean 使用而是作為單個對象的工廠.

當通過 Bean 名稱獲取 FactoryBean 實例時,獲取到的并不是FactoryBean對象本身,而是FactoryBean對象 getObject()方法返回的對象

BeanFactory:定義獲取bean及bean的各種屬性。

HierarchicalBeanFactory:繼承BeanFactory,也就是在BeanFactory定義的功能的基礎上增加了對parentFactory的支持。

SingletonBeanRegistry:定義對單例的注冊及獲取。


DefaultSingletonBeanRegistry:對接口SingletonBeanRegistry各函數的實現。


AutowireCapableBeanFactory:提供創建bean、自動注入、初始化以及應用bean的后處理器。


spring IOC 常用類介紹

BeanPostProcessor 注冊時機與執行順序

BeanPostProcessor有很多個,而且每個BeanPostProcessor都影響多個Bean,其執行順序至關重要,必須能夠控制其執行順序才行。關于執行順序這里需要引入兩個排序相關的接口:PriorityOrdered、Ordered

 

PriorityOrdered、Ordered接口作為Spring整個框架通用的排序接口,在Spring中應用廣泛,也是非常重要的接口。

 

1 PriorityOrdered是一等公民,首先被執行,PriorityOrdered公民之間通過接口返回值排序

2 Ordered是二等公民,然后執行,Ordered公民之間通過接口返回值排序

3 都沒有實現是三等公民,最后執行

//在以下源碼中,可以很清晰的看到Spring注冊各種類型BeanPostProcessor的邏輯,//根據實現不同排序接口進行分組。優先級高的先加入,優先級低的后加入。// 首先,加入實現了PriorityOrdered接口的BeanPostProcessors,順便根據PriorityOrdered排了序String[] postProcessorNames =  beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {  if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));    processedBeans.add(ppName);  }}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();// 然后,加入實現了Ordered接口的BeanPostProcessors,順便根據Ordered排了序postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {  if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));    processedBeans.add(ppName);  }}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();// 最后加入其他常規的BeanPostProcessorsboolean reiterate = true;while (reiterate) {  reiterate = false;  postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);  for (String ppName : postProcessorNames) {    if (!processedBeans.contains(ppName)) {      currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));      processedBeans.add(ppName);      reiterate = true;    }  }  sortPostProcessors(currentRegistryProcessors, beanFactory);  registryProcessors.addAll(currentRegistryProcessors);  invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);  currentRegistryProcessors.clear();}//根據排序接口返回值排序,默認升序排序,返回值越低優先級越高。PriorityOrdered、Ordered接口作為Spring整個框架通用的排序接口,在Spring中應用廣泛,也是非常重要的接口。

 

 

分享到:
標簽:容器 IOC
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定