Spring 源码分析 总结1

Spring主要功能就是ioc和aop
Spring认为所有的组件都应该放在ioc容器中,所有的组件靠容器来自动装配,也就是依赖注入

ioc容器的创建过程:

当我们创建一个ioc容器时,比如说一个AnnotationConfigApplicationContext时,会调用它的构造方法,点进去发现有一个重要的方法refresh()
来自https://blog.csdn.net/simple_122/article/details/94221743
1 prepareRefresh() ,创建前的预处理:初始化一些属性设置,检查属性的合法性,保存容器中的一些早期的事件
2 obtainFreshBeanFactory() :创建并获取BeanFactory
3 prepareBeanFactory() :BeanFactory的一些预准备工作,比如说beanFactory进行一些设置(类加载器,bean的后置处理器什么的)
4 postProcessBeanFactory(): beanFactory准备工作做完后的一些后置处理工作,这个方法是空的,留给子类重写,实现子类在创建并准备好beanFactory后进行进一步的设置
=========以上是BeanFactory的预处理和准备工作
5 invokeBeanFactoryPostProcessors() :执行BeanFactory的后置处理器的一些方法
6 registerBeanFactoryPostProcessors():注册BeanFactory的后置处理器
7 initMessageSource(): 初始化MessageSource组件,做国际化功能,消息绑定,消息解析
8 initApplicationEventMulticaster(): 初始化容器事件派发器
9 onfresh(): 留给子类,子类通过重写这个方法,可以在容器刷新时自定义一些逻辑
10 registerListener(): 给容器中注册所有项目里面的ApplicationListener
11 finishBeanFactoryInitialization(): 初始化容器中剩下的Bean,我们自定义的bean都是这时候创建并初始化,
1)获取容器中所有的bean,依次进行初始化,创建
2)获取bean的定义信息
3)判断bean不是抽象的,是单实例的,不是懒加载,是不是工厂bean(看实现没FactoryBean接口),不是工厂bean就通过getName()创建对象,先从缓存(singletonObject)中取,如果有,说明之前创建过,没有的话就创建,
4) 初始化bean,注册bean的销毁方法
5) 创建好了放入singletonObject中
12 finishRefresh(): 完成ioc容器的创建

IOC

使用注解开发的话就是用配置类代替配置文件xml,

组件注册
AnnotationConfigApplicationContext可以理解为Spring的用注解注册的容器,取bean都是从这里面getBean(),ioc容器中默认加的都是单实例的
返回是true
使用@Scope改变作用域
prototype:多实例的,ioc容器启动就不会调用方法了,getBean的时候才调用方法创建实例的,多实例嘛,获取几次bean就调用几次方法创建对象,
singleton:单实例的,默认的,ioc容器启动就会调用方法创建对象实例到ioc容器中,有点像单例中的饿汉模式,以后每次获取都是直接从容器中拿,类似map.get()
request,session基本上用不到
用@Configuration来告诉spring这是一个配置类

@Bean 给容器中注册一个bean,加在方法上,但通常会用于添加对象到容器中(在配置类或其他地方),类型是返回值的类型,名字默认为方法名,类型就是返回值的类型
@Bean(“person01”) 就会将bean的名字改为person01
public Person person(){
return new Person();
}
@ComponentScan** 包扫描,加在配置类头顶,value可以指定要扫描的包 ,excludeFilters 可以用来排除不想被扫描的包,可以写多个ComponentScan
格式如下:按照注解的方式排除了有controller注解的包
注意,用includeFilters的时候要排除默认的扫描模式
在这里插入图片描述
在这里插入图片描述
使用自定义规则的时候,必须要有一个实现typeFilters的实现类
懒加载:Spring 的ioc容器默认单实例,而且是饿汉模式不是懒汉模式,在ioc容器创建的时候就创建好实例放在容器中了,可能会浪费资源,可以用 @Lazy换成懒加载(针对不常用的bean,在容器启动的时候不创建对象实例,而是第一次调用bean的时候创建,并进行初始化)
在这里插入图片描述

@Conditional({Conditon}) ,按照一定的条件进行判断,满足条件给容器注册Bean,如果去看springBoot源码会发现(我还没有看过),springBoot 中大量使用了该注解,可以用在类上,也可以用在方法上(在方法上创建bean,就标在方法上),判断条件是实现Conditon接口的重写matches方法的 实现类,而且这个注解传入的参数是个conditon数组哦,
例如:
有两个person对象,一个叫windows,一个叫linux,我想根据运行环境来注册Bean,比如说是windows就把叫windows的person对象注册进入ioc容器
在这里插入图片描述

LinuxCondition的具体写法,其中的4注册类非常灵活,比较它包含ioc容器中所有的bean的定义信息,可以根据ioc容器中有什么bean来实现判断条件,甚至还可以在这注册一个bean

注册时添加@Conditional注解,这样如果我们的环境是Linux,就会给ioc容器中注册这个bean
如果@Conditional注解放在配置类上,满足这个conditon条件后,这个配置类中所有的Bean才会生效,去注册到ioc容器中

@Import(类.class),
1 加在配置类头上,可以快速的给ioc容器中导入一个包,id默认为组件的全类名(包.类),
还可以一次性导入多个@Import({color.class,red.class})
2 ImportSelector返回需要导入的组件的全类名数组,需要有一个实现ImportSelector接口的实现类
@Import({color.class,red.class,MyImportSelector.class})
在这里插入图片描述
3 ImportBeanDefinitonRegistrar:
@Import({color.class,red.class,MyImportSelector.class,MyImportBeanDefinitonRegistrar.class})
RootBeanDefiniton:就是注册bean的类型信息,作用域等
在这里插入图片描述
使用FactoryBean(工厂bean)
在这里插入图片描述
在这里插入图片描述
虽然看到好像是生成了一个叫MyFactoryBean的Bean组件,通过ioc容器ApplicationContext.getBean(“MyFactoryBean”)得到就是color,就是color 的bean工厂 MyFactoryBean中的getObject()方法返回的对象。很重要哦,用的很多
但是如果就是想获得MyFactoryBean类型的Bean,只需要
ApplicationContext.getBean("&MyFactoryBean"),就可以了

总结
给容器中注册组件:
1包扫描+组件标注注解(@Controller/@Service/@Repository/@Component),
有局限性,可以在自己写的类上加这些注解,如果是导入的jar包,我们不能给他们加上这些注解
2@Bean[导入的第三方包的组件,单例模式]
3@Import[快速的给容器中导入一个包],springboot中用他的第二种方式ImportSelector很多
4 FactoryBean工厂bean
1)默认获得是工厂Bean调用getObject创建的对象
2)要获取工厂bean本身,需要给id前面加&

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值