spring框架学习-IOC(BeanDefinition注册流程)

329 阅读3分钟

学习spring框架的心得与总结。附:spring源码注释地址github.com/LXPWing/spr…

BeanDefinition注册流程图(XML):www.processon.com/view/link/6…

IOC

先认识spring架构(简易图) www.processon.com/view/link/6…

基础接口(重点)

  • BeanDefinition

官方注释:A BeanDefinition describes a bean instance, which has property values,constructor argument values, and further information supplied by concrete implementations. 继承树图

image.png

BeanDefinition存储了用户自定义组件和spring基础组件信息。

建议:Debug时可以给RootBeanDefinition构造函数打断点进行流程跟踪。

  • BeanDefinitionHolder

1、Holder for a BeanDefinition with name and aliases.

2、Can be registered as a placeholder for an inner bean.

3、Can also be used for programmatic registration of inner bean definitions. If you don't care about BeanNameAware and the like,registering RootBeanDefinition or ChildBeanDefinition is good enough.

image.png

BeanDefinitionHolder用于保存BeanDefinition和beanName信息。

  • DefaultListableBeanFactory

image.png

DefaultListableBeanFactory拥有许多缓存池用于获取和存储Bean,存储单实例Bean在DefaultSingletonBeanRegistry类(DefaultListableBeanFactory的父类)的singletonObjects池中。(你可能会疑惑什么是Bean?在这里先大概了解下Bean,Bean是spring通过反射创建的一个你需要的实例对象(不一定是反射也可以使用new),后期将会详细讲解Bean)

建议:留意下DefaultSingletonBeanRegistry类中的singletonFactoriesearlySingletonObjectsregisteredSingletons这三个缓存池,后期将涉及循环依赖

  • BeanFactory

首先看BeanFactory的继承图

image.png 可以发现BeanFactory是IOC容器的顶级接口,再去浏览BeanFactory中方法你就会发现它就是一个工厂用于生产Bean(工厂模式)。

image.png

拓展:ListableBeanFactory接口:保存IOC的核心信息,AutowireCapableBeanFactory接口:自动装配,HierarchicalBeanFactory接口 :定义父子工厂

  • ApplicationContext

IOC容器接口,其他类通过继承ApplicationContext接口拓展组件注册方式。例如: AnnotationConfigApplicationContext,ClassPathXmlApplicationContext等

  • BeanPostProcessor

Bean的后置处理器(干预Bean的生成),需要注意InstantiationAwareBeanPostProcessorMergedBeanDefinitionPostProcessorSmartInstantiationAwareBeanPostProcessor这三个接口。

  • BeanFactoryPostProcessor

BeanFactory的后置处理(干预BeanFactory的生成)。

  • InitializingBean

Bean的生命周期。当创建一个bean并将该bean交给spring的ioc容器管理时,便会调用InitializingBean接口,在设置完bean的属性后调用afterPropertiesSet()做bean的参数检查以及在加入容器之前要做的一些准备工作。

BeanDefinition注册流程(XML)

<?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" >
        
    <bean id="cat" class="com.Li.spring.processor.entity.Cat">
        <property name="name" value="xiaomao"></property>
        <property name="age" value="90"></property>
    </bean>
    
</beans>
@Component
public class Cat implements ApplicationContextAware {
    private String name;
    
    private Integer age;
    
    private ApplicationContextAware applicationContextAware;
    
    public Cat() {
        System.out.println("这里是Cat");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContextAware=applicationContextAware;
    }
}
@ComponentScan("com.Li.spring")
public class main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:beans.xml");
        Cat cat = (Cat)classPathXmlApplicationContext.getBean("cat");
        System.out.println(cat.getAge());
   }
}

首先new ClassPathXmlApplicationContext创建容器,调用 ClassPathXmlApplicationContext的构造方法执行里面的refresh方法。

image.png

refresh是调用其父类AbstractApplicationContext的方法,当执行到obtainFreshBeanFactory()时,obtainFreshBeanFactory()会创建工厂并将XML中的配置装配到BeanDefinition中存储在DefaultListableBeanFactory的缓存池中。

image.png obtainFreshBeanFactory()方法将会调用AbstractRefreshableApplicationContext类的refreshBeanFactory(),refreshBeanFactory()会创建DefaultListableBeanFactory(Bean的蓝图库),然后进入loadBeanDefinitions(beanFactory)方法加载全部的BeanDefinition信息

image.png

调用AbstractXmlApplicationContext类中的loadBeanDefinitions(beanFactory)方法,创建XmlBeanDefinitionReader(XML内容读取器)并设置参数。

image.png

进入同类下的loadBeanDefinitions(beanDefinitionReader),获得xml文件路径

image.png

调用AbstractBeanDefinitionReader类下的loadBeanDefinitions(String location, @Nullable Set actualResources) 创建并使用ResourceLoader加载XML资源

image.png

进入loadBeanDefinitions(resources)方法,调用XmlBeanDefinitionReader类下的doLoadBeanDefinitions(InputSource inputSource, Resource resource),使用W3C进行XML文件解析,将文件内容转换为Document对象

image.png

进入registerBeanDefinitions(doc,resource)方法,创建BeanDefinitionDocumentReader(Document解析器)

image.png

进入documentReader.registerBeanDefinitions(doc, createReaderContext(resource))方法,调用DefaultBeanDefinitionDocumentReader类下的doRegisterBeanDefinitions(Element root)方法,创建BeanDefinitionParserDelegate(BeanDefinition解析代理类),接下来将对xml中的大标签进行解析。

image.png

createDelegate(getReaderContext(), root, parent)方法调用BeanDefinitionParserDelegate类下的populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root)解析大标签

image.png

解析完大标签,回到doRegisterBeanDefinitions(Element root)方法,执行parseBeanDefinitions(root,this.delegate)方法解析小标签

image.png

进行解析小标签。

image.png

当解析完小标签时,调用processBeanDefinition(ele, delegate),创建BeanDefinitionHolder对BeanDefinition封装

image.png

以上步骤是对XML文件的解析和BeanDefinition封装,接下来是将BeanDefinition注册到工厂里。

调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())将BeanDefinition注册到DefaultListableBeanFactory中

image.png

完成XML方式的BeanDefintion注册。