Spring-Beans

spring-beans模块笔记 整理了关键接口和实现类,部分常用注解和一些流程说明


核心接口

BeanFactory-顶层Bean工厂接口.主要提供getBean方法

-ListableBeanFactory-对BeanFactory接口的增强.增加了很多getBeanXXX_By_XXX方法

-HierarchicalBeanFactory-对BeanFactory接口的增强.可以设置parent的BeanFactory

   --ConfigurableBeanFactory-接入可配置的选项.主要是内部框架使用时的设置拓展对象   

-AutowireCapableBeanFactory-对BeanFactory接口的增强.增加了实例的依赖解析/注入相关api

       ---ConfigurableListableBeanFactory-对BeanFactory以及几个增强能力的聚合接口,代码中不推荐使用应当根据需要使用真实的接口

这几个接口是非常核心的接口,实际上容器的默认实现DefaultListableBeanFactory在继承体系中一层层的都实现了这几个接口的功能

常见接口

Aware-顶层标记接口,根据BeanFactory注释中说的"推送配置优于拉配置”的理念,所有bean增强的能力都是通过接口的方式推给你的,你不用自己去拉

FactoryBean-高级组件,自定义Bean的初始化与其他配置,它的依赖应当通过构造函数或BeanFactoryAware编程式的获取

SmartFactoryBean-支持设置早期初始化行为

SmartInitializingSingleton-类似于InitializingBean,这是在BeanFactory完成之后的回调

BeanDefinition-对Bean进行描述的接口,可以获取构造参数/属性值/依赖项/

-AnnotatedBeanDefinition-对BeanDefinition接口的增强,引入了注解元信息,目前使用较多

BeanFactoryPostProcessor-调整Bean定义和调整BeanFactory的配置,框架的很多特性都是通过这个接口实现的,比如BeanDefinition中的字符串占位符解析,以及更灵活的对BeanFactory的配置支持

BeanFactoryPostProcessor用的非常多,很多高级特性实现都是基于它

BeanReference-通过BeanName在运行期进行实际Bean实例的引用替换,在BeanDefinition阶段使用较多,因为这时候还没有Bean实例,通过这种引用来建立实际依赖的,比如它的实现类RuntimeBeanReference

Scope-定义了Bean的范围概念,在单例和原型模式之外的Bean的生命周期如果想要控制的话(e.g:request/session)都是通过定义Scope来实现的

ObjectFactory-内部自己用的Bean提供策略,类似于FactoryBean不过没有定义更详细的细分接口,只有一个getObject,具体规则实现类自己定

AliasRegistry-别名注册器顶层接口,BeanFactory都要支持别名,如SimpleAliasRegistry就是简单的Map实现


关键实现类

BeanDefinitionVisitor-通过访问者模式对BeanDefinition中占位符进行替换

XxxResolver-很多Resolver都是主流程的部分具体实现拆出来的,不然主流程就太长了.比如ConstructorResolver是实例化部分的实现,BeanDefinitionValueResolver是对依赖的构造函数值/方法值进行解析.RuntimeBeanReference的实现部分就在这里

BeanFactory的继承体系

这里的实现类介绍主要就是这里的右面继承体系中涉及的类

SimpleAliasRegistry-顶层基类,引入AliasRegistry(别名注册器)接口,并实现部分子接口ConfigurableBeanFactory的功能

DefaultSingletonBeanRegistry-继承SimpleAliasRegistry,引入SingletonBeanRegistry(单例Bean注册器)接口,并实现部分子接口ConfigurableBeanFactory的功能

FactoryBeanRegistrySupport-继承DefaultSingletonBeanRegistry,主要增加一些FactoryBean注册的方法供子类调用

AbstractBeanFactory-继承FactoryBeanRegistrySupport,引入主要配置接口ConfigurableBeanFactory,定义了getBean的流程(这里主要是递归加载依赖Bean,优先处理单例和原型,最后根据scope自定义范围)以及一些抽象方法(如createBean)让子类实现

AbstractAutowireCapableBeanFactory-继承AbstractBeanFactory,引入自动装载拓展接口AutowireCapableBeanFactory.主要定义了createBean流程,它主要是创建Bean,初始化Bean

DefaultListableBeanFactory-继承自AbstractAutowireCapableBeanFactory,引入进一步增强的三合一接口ConfigurableListableBeanFactory和BeanDefinitionRegistry

可以看到这里在继承体系中逐步的拆解了几个核心接口的功能,不过很多接口的实现都很特别,通过实现类与接口平行的结构进行实现,随后在子类中通过继承与接口实现再合并.


BeanFactory核心方法

registerBeanDefinition(提供外部注册bean定义)

getBean(最常用的接口.实际上此接口只负责分区域加载,不负责具体创建)

createBean(核心实例化,初始化流程.可选自动注入类型等)

createBean和getBean的流程是互相嵌套递归.getBean的时候需要自己对依赖getBean到最后还需要创建Bean,创建Bean的时候需要对初始化依赖的参数再getBean.最终解开层层嵌套,进而创建无依赖的Bean(环形的属性依赖会使用占位符先解开依赖问题)

理解这几句话对创建Bean的流程有很大的帮助

环形依赖问题:环形依赖可能出现在单例中的构造函数互相依赖或者原型模式中的属性依赖,如果只是单例属性依赖的话不会造成环形依赖.


创建Bean时的部分生命周期回调

BeanPostProcessor-调整Bean实例,甚至可以替换,大多数情况使用这个进行创建Bean的代理来拓展一些Bean行为.这是在初始化前后的回调

BeanPostProcessor用的也非常多,简单的加代理行为基本都是通过它实现

InstantiationAwareBeanPostProcessor-在bean实例化前后进行回调也就是Class --> Bean这个转换过程以及初始化之前,主要是决定替换代理的

MergedBeanDefinitionPostProcessor-在实例化之后与初始化之前的回调.可以解析BeanDefinition,比如说AutowiredAnnotationBeanPostProcessor就是在这里实现的解析需要注入的属性放入缓存中,以便在后面直接使用


createBean生命周期的回调接口顺序

1.InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation实例化之前进行调用,如果返回空,会直接调用BeanPostProcessor.postProcessAfterInitialization方法进行初始化前置.如果返回了自定义的Bean,那么不会进行属性注入.直接返回

2.MergedBeanDefinitionPostProcessor实例化之后的回调,可以对BeanDefinition进行信息获取

3.InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation属性注入分析之前进行调用.这里主要是给与使用者自己进行注入的机会,一旦自己进行属性配置,那么将不会进行属性解析

4初始化
4.1先调用Aware方法注入,BeanNameAware,BeanClassLoaderAware,BeanFactoryAware等

4.2调用BeanPostProcessor执行前置方法postProcessBeforeInitialization

4.3调用afterPropertiesSet或自定义初始化方法

4.4最后调用BeanPostProcessor执行后置方法postProcessAfterInitialization结束初始化


createBean方法注入流程

AutowireByType流程

1先处理@Value注解

2处理容器类型,Array,Collection,Map类型

3处理同类型多个Bean,@Primary 先获取,其次@Order 排序较高的再处理

4最后如果要求注入的类型非容器类型,而且必须要求注入,那么直接报错没找到类

AutowireByName流程

直接通过属性名调用getBean方法获取bean,注入属性中,没找到直接报错


关键注解功能描述

@Autowired-自动注入.其还可以支持注入Collection和Map(key-beanName,value-Bean),Array类型的属性

@Qualifier-多个类型相同的Bean,进行@Autowired时对beanName的进一步限制,支持自定义新的限定注解

@Value-注入SPEL表达式

@Lookup-以注解的方式在方法级解决原型模式对象依赖的问题

@Required-标记依赖为必须项

@Configurable-非Spring管理的容器,获取自动装配能力


FactoryBean在beans包中的使用

Spring提供了很多很有用的FactoryBean,是为了在声明Bean时尽可能的提供更灵活的方式,这里看下

AbstractFactoryBean<T>:实现了FactoryBean的简单模板超类,它根据标志来决定是创建一个单例还是一个prototype对象。

FieldRetrievingFactoryBean:静态方法或普通方法的调用转换

ListFactoryBean:声明一个List作为Bean

MapFactoryBean:声明一个Map作为Bean

SetFactoryBean:声明一个Set作为Bean

MethodInvokingFactoryBean:用以指定方法调用的返回值作为一个Bean

ObjectFactoryCreatingFactoryBean:返回一个ObjectFactory包装的对象,它通过beanName从容器get对象

PropertiesFactoryBean:它支持从classpath位置的文件中读取配置对象作为实例返回

PropertyPathFactoryBean:通过指定的bean,以及指定的属性作为一个Bean对象

ProviderCreatingFactoryBean:返回一个Provider包装的对象,它通过beanName从容器get对象

ServiceLocatorFactoryBean:一般在注入属性需要原型模式时使用,通过反射每次获取对象时确保为新对象

ServiceFactoryBean-适配ServiceLoader获取第一个Service作为一个Bean对象

ServiceListFactoryBean-适配ServiceLoader获取所有的Service作为一个Bean对象

ServiceLoaderFactoryBean-直接返回ServiceLoader作为一个Bean对象


BeanFactoryPostProcessor在beans包中自身的特性实现

ConfigurationClassPostProcessor-引导配置解析的核心类,非常重要,这是context包的内容这里不细说

PlaceholderConfigurerSupport-将所有的BeanDefinition中的占位符(${})进行了替换

CustomScopeConfigurer-允许自定义的Scope注册

CustomAutowireConfigurer-允许自定义的@Qualifier限定注解注册

CustomEditorConfigurer-允许自定义的PropertyEditor注册

DeprecatedBeanWarner-检测一下@Deprecated弃用注解,匹配的话日志警告一下


标准Bean生命周期接口以及完整的初始化方法及其标准顺序

自上向下依次为:
创建时
BeanNameAware's {@code setBeanName}

BeanClassLoaderAware's {@code setBeanClassLoader}

BeanFactoryAware's {@code setBeanFactory}

EnvironmentAware's {@code setEnvironment}

EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}

ResourceLoaderAware's {@code setResourceLoader}

ApplicationEventPublisherAware's {@code setApplicationEventPublisher}

MessageSourceAware's {@code setMessageSource}

ApplicationContextAware's {@code setApplicationContext}

ServletContextAware's {@code setServletContext}

{@code postProcessBeforeInitialization} methods of BeanPostProcessors

InitializingBean's {@code afterPropertiesSet}

a custom init-method definition

{@code postProcessAfterInitialization} methods of BeanPostProcessors

关闭时

{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors

DisposableBean's {@code destroy}

a custom destroy-method definition

Aware部分实现在context包的ApplicationContextAwareProcessor中,它是一个BeanPostProcessor

beans包中主要实现了在类初始化前后的回调,以及创建/初始化等也就是BeanPostProcessor,InitializingBean.其他的Aware都是基于此进行的拓展

已经标出了常用的一些接口,这里能看到可以获取的Aware配置也能看到他们的顺序


总结

1整个beans包的类非常的多,之前接触的很多特性实现都是在这个包内实现的

2很多接口声名的很简单,在实现类中很多public方法是子接口声名的,既没有在原顶层接口增加新方法,又保持了各个接口实现的独立性,可以借鉴下

3实现一个复杂流程可以采用XxxResolver将部分流程委托出去进行处理,如果需要内部一些方法将自己也传出去

4在建立自定义流程时需要增加自己的特性,可以采用包装类的方式在实现时进行类型判断处理.比如RuntimeBeanReference,ManagedList等

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容