大綱
- 容器的基本用法
- 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中應用廣泛,也是非常重要的接口。