您的位置:首页 > 编程语言 > Java开发

分析spring源码第五(三)篇:Spring中Bean的解析、加载、创建 过程总结

2018-08-30 16:25 916 查看
一、IOC type
1.Xml               -- 配置bean
2.Annotation        -- @Compoment
3.Class             -- @Configuration
4.Properties,YML    -- @EnableConfigurationProperties(User.class)   @ConfigurationProperties("bnb.user")

二、IOC 注入方式
1.Setter
2.Constructor
3.Factory-method

三、Why IOC
1.模块化
2.可重用性
3.易于扩展
4.可维护

四、Spring IOC API
1.BeanDefinition                  -- 描述bean的实例,有属性值,构造参数值
2.Resource and ResourceLoader     -- 资源和加载资源
3.BeanFactory                     -- spring bean容器的根接口,定义了容器最基本的功能
4.ApplicationContext              -- 为应用程序提供配置的中心接口

五、Spring IOC  process resource

核心: XML -->  c  --> BeanWrapper(实现依赖注入与类型转化) -> Object (获取我们要的对象)

1. BeanDefinition 处理过程

xml or properties ---> ResourceLoader  --->  Resource  --> XXXReader (XmlBeanDefinitionReader/)  -->  BeanDefinition   (主要是这两种解析值的形式  ConstructorArgumentValues 和 MutablePropertyValues)

new ClassPathXmlApplicationContext("")
-->  org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory
-->  org.springframework.context.support.AbstractApplicationContext.refreshBeanFactory
-->  org.springframework.context.support.AbstractRefreshableApplicationContext.loadBeanDefinitions
-->  org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)

最终XML解析 是在BeanDefinitionParserDelegate类中完成的

2. BeanWrapper  处理过程
Spring的基础设施的中心接口,继承以下四个接口:
ConfigurablePropertyAccessor
PropertyAccessor
PropertyEditorRegistry
TypeConverter

3. 依赖注入过程
Java实例过程:   创建对象  -->  设置属性 --> 初始化方法
IOC实例化过程:   CreateBeanInstance  -->  populateBean  -->  initializeBean

CreateBeanInstance    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean

4.spring 类型转换
类型转换核心类 TypeConverterDelegate 方法 convertIfNecessary
ConversionService
PropertyEditor

5.spring 容器扩展

BeanPostProcessor :定制化bean逻辑,bean 后置处理器   典型应用场景:

注解式依赖注入  @Autowired  @Value    AutowiredAnnotationBeanPostProcessor  (依赖注入的过程 其实就是根据注解获取注解bean的对象值,然后根据Java反射将bena注入进去)

AOP的实现

Spring容器感知

六.
总结 IOC 过程 BeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("beanUserTest.xml"));
1. xml -> ResourceLoader -> Resource
2.XmlBeanDefinitionReader.loadBeanDefinitions(resource) -> XmlBeanDefinitionReader.loadBeanDefinitions(new EncodedResource(resource))
3.XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource)
3.1. 将resource转化成document                        Document doc = XmlBeanDefinitionReader.doLoadDocument(inputSource, resource)     ->  DocumentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,getValidationModeForResource(resource), isNamespaceAware());
3.2. reader读取document为注册beanDefinition作准备     XmlBeanDefinitionReader.registerBeanDefinitions(Document doc, Resource resource) ->  DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(Document doc, XmlReaderContext readerContext) -> DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)
3.3. 用自定义或默认解析器解析element                   DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)      ->  DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) -> delegate.parseDefaultElement(ele) / delegate.parseCustomElement(root)
3.4. 用默认解析器解析element过程     DefaultBeanDefinitionDocumentReader.parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
3.4.1  包含import标签的,则找出引入的resource最后在递归调用loadBeanDefinitions(resource)再次解析  DefaultBeanDefinitionDocumentReader.importBeanDefinitionResource(Element ele) -> AbstractBeanDefinitionReader.loadBeanDefinitions(Resource... resources) ->  XmlBeanDefinitionReader.loadBeanDefinitions(Resource resource)
3.4.2  包含alias别名的,解析出bean的别名并在aliasRegistered进行注册  DefaultBeanDefinitionDocumentReader.processAliasRegistration(Element ele) ->  ReaderContext.fireAliasRegistered(name, alias, extractSource(ele)) -> EmptyReaderEventListener.aliasRegistered(AliasDefinition aliasDefinition)
3.4.3  包含bean标签的,则解析出bean并进行bean的注册到map中   DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)  ->  BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele) -> BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())
3.4.4  包含beans标签的 又重新进入3.2步 DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)
4.获取bean xmlBeanFactory.getBean("test"), AbstractBeanFactory.getBean(name) -> AbstractBeanFactory.doGetBean(name,requiredType)
4.1  转化成真正的bean名,name可能是别名或工厂名等   String beanName = transformedBeanName(name)
4.2  从缓存中获取单利bean,获取到则返回 Object sharedInstance = getSingleton(beanName)
4.3 如果4.2 没有获取到,则获取bean的所有依赖,并将依赖进行注册和创建  String[] dependsOn = mbd.getDependsOn() ->  DefaultSingletonBeanRegistry.registerDependentBean(dep, beanName) -> AbstractBeanFactory.getBean(dep);
4.4 如果是单例 mbd.isSingleton(),  AbstractAutowireCapableBeanFactory.createBean(beanName, rootBeanDefinition,args)
4.4.1 给BeanPostProcessors处理器一个返回代理而不是目标bean实例的机会。   AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)
4.4.1.1  实例化前置处理器 applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)
4.4.1.2  实例化后置处理器 applyBeanPostProcessorsAfterInitialization(bean, beanName)
4.4.2 创建bean,  doCreateBean(beanName, mbdToUse, args)
4.4.2.1  创建bean实例对象   createBeanInstance(beanName, mbd, args)
4.4.2.1.1    有指定的构造函数的创建bean对象  autowireConstructor(beanName, mbd, null, null)
4.4.2.1.2    使用默认构造函数创建bean对象   instantiateBean(beanName, mbd)
4.4.2.2  设置属性,填充值   populateBean(beanName, mbd, instanceWrapper)  给任何实例化的后置处理器修改的机会 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)
4.4.2.3  初始化bean       initializeBean(beanName, exposedObject, mbd)
4.4.2.3.1   更改BeanNameAware/BeanClassLoaderAware/BeanFactoryAware     invokeAwareMethods(beanName, bean)
4.4.2.3.2   执行所有getBeanPostProcessors的初始化的前置方法                applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
4.4.2.3.3   执行bean的初始化方法                                          invokeInitMethods(beanName, wrappedBean, mbd)   ->  ((InitializingBean) bean).afterPropertiesSet()
4.4.2.3.4   执行所有getBeanPostProcessors的初始化的后置方法                applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
4.4.3  从bean实例中获取object,   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
4.5 如果是多例 mbd.isPrototype()  则创建一个新的实例对象
4.5.1  将创建中的多例bean存入ThreadLocal<Object> prototypesCurrentlyInCreation =new NamedThreadLocal<Object>中,    beforePrototypeCreation(beanName);
4.5.2  将建bean对象                createBean(beanName, mbd, args)
4.5.3  将bean从4.5.1中的prototypesCurrentlyInCreation移除        afterPrototypeCreation(beanName)
4.5.5  从bean实例中获取object,   bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

七.介绍 初始化bean的一些方法的执行顺序

1、init-method方法,初始化bean的时候执行,可以针对某个具体的bean进行配置。init-method需要在applicationContext.xml配置文档中bean的定义里头写明。例如:<bean id="TestBean" class="nju.software.xkxt.util.TestBean" init-method="init"></bean>
这样,当TestBean在初始化的时候会执行TestBean中定义的init方法。

2、afterPropertiesSet方法,初始化bean的时候执行,可以针对某个具体的bean进行配置。afterPropertiesSet 必须实现 InitializingBean接口。实现 InitializingBean接口必须实现afterPropertiesSet方法。

3、BeanPostProcessor,针对所有Spring上下文中所有的bean,可以在配置文档applicationContext.xml中配置一个BeanPostProcessor,然后对所有的bean进行一个初始化之前和之后的代理。BeanPostProcessor接口中有两个方法: postProcessBeforeInitialization和postProcessAfterInitialization。 postProcessBeforeInitialization方法在bean初始化之前执行, postProcessAfterInitialization方法在bean初始化之后执行。

总之,afterPropertiesSet 和init-method之间的执行顺序是afterPropertiesSet 先执行,init-method 后执行。从BeanPostProcessor的作用,可以看出最先执行的是postProcessBeforeInitialization,然后是afterPropertiesSet,然后是init-method,然后是postProcessAfterInitialization。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: