大话spring~spring那些事

Spring框架简化了Java开发,通过IOC容器管理Bean,实现无缝对接和自动初始化。容器利用Map缓存Bean,提供快速访问。流程包括定位配置、加载Class、注册Bean并进行依赖注入。BeanFactory与ApplicationContext的区别在于功能的全面性。Spring的AOP通过动态代理实现切面编程。
摘要由CSDN通过智能技术生成

说到这个spring,首先要搞清楚没有spring之前我们是什么样子的哈

 a、很多设计模式需要自己去整合
 b、所有的封装、继承、多态、增强、依赖、模块管理等等工作都需要自己制定统一的规则
 c、所有的创建对象、配置依赖关系、资源的重复利用都需要我们手动去搞

我滴个天,看着都累、这的做多少重复的工作。人是懒惰的,不想重复造轮子呀,所以Spring出现了,Java程序员的春天真的来了,解放了

细节来了,spring做了什么?让 Java Bean能够实现无缝对接、闭上眼睛幻想一下,有没有这么一个东西、我们的所有bean 初始化就都准备好了,只是存在一个地方、用的时候就自动来了~正所谓召之即来。想想都香、简直是人工智能。

幸运的是,spring就做到了。这个得益于spring的IOC容器,ioc小名bean工厂,在具体点就是一个(Map容器–ps:实际存在 ConcurrentHashMap)、缓存bean 的地方。这么搞得优点显而易见,时刻在内存中放着、用的时候不需要临时创建,速度那是杠杠的~
用抽象点的语言描述:

1、IOC(Inversion of Control)控制反转:所谓控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让容器知 道需要创建的对象与对象的关系。这个描述最具体表现就是我们可配置的文件。

简单点说就是容器帮我们创建bean,并理清楚bean与bean之前的关系,最后存起来供我们使用。如何创建?如何存?通过啥规则顺序加载?

总结:ioc 全局上下文缓存的信息 IOC容器何时创建bean、各个bean的关系、怎么存储bean
spring容器是整个spring框架的核心,通常我们说的spring容器就是bean工厂
bean工厂负责创建和初始化bean、装配bean

见识一下bean长啥样子?

ApplicationContext(XmlWebApplicationContext  :-Root WebApplicationContext startup)
	serializationde==org.springframework.web.context.WebApplicationContext:
	-—beanFactory
	--beanDefinitionMap(ConcurrentHashMap  ===key:value)
	ApplicationContext,这是在BeanFactory基础之上,面向使用Spring框架的开发者。提供了一系列的功能!

1、"key:restTemplate" -> "Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=restTemplateConfig; factoryMethodName=restTemplate; initMethodName=null; destroyMethodName=(inferred); defined in com.esgcc.fsp.config.RestTemplateConfig"

流程细化:定位 加载 注册 自动依赖注入
在这里插入图片描述
流程图看着很复杂,简单概括一下
1、定位:加载配置文件,找到 .class的存放位置
2、加载:根据路径 找到class文件、packname+filename 存List
3、注册:class.forname() 反射class, 拿到注解、创建对象bean,存入map -
4、依赖注入:遍历map,反射每个class的字段,有@auto 注解 就赋值
以上是对spring的一个简单的概括,真正的spring肯定在这个理念上加强了好多。

1、BeanFactory 和 ApplicationContext 有什么区别?

BeanFactory 可以理解为含有 bean 集合的工厂类。BeanFactory 包含了种 bean 的定义,以便在接 收到客户端请求时将对应的 bean 实例化。 BeanFactory 还能在实例化对象的时生成协作类之间的关系。此举将 bean 自身与 bean 客户端的配置 中解放出来。BeanFactory还包含了bean生命周期的控制,调用客户端的初始化方法(initialization Methods)和销毁方法(destruction Methods)。 从表面上看,application context 如同 bean factory 一样具有 bean 定义、bean 关联关系的设置, 根据请求分发 bean 的功能。但 application context 在此基础上还提供了其他的功能。
1.提供了支持国际化的文本消息
2.统一的资源文件读取方式 
3.已在监听器中注册的 bean 的事件

spring源码是啥?
1、定位:资源配置 import、classpath、url
2、加载:解析配置文件,把bean包装成 beanDefintion对象
3、注册:把已经初始化的beanDefintion对象放入IOC-map容器
资源定位

此处可通过xml,定位 class
	//根据 Xml 配置文件创建 Resource 资源对象,该对象中包含了 BeanDefinition 的信息
	ClassPathResource resource =new ClassPathResource("application-context.xml");
	//创建 DefaultListableBeanFactory
	DefaultListableBeanFactory factory =new DefaultListableBeanFactory();
	//创建 XmlBeanDefinitionReader 读取器,用于载入 BeanDefinition。之所以需要 BeanFactory 作为参数,是因为会
	将读取的信息回调配置给 factory
	XmlBeanDefinitionReader reader =new XmlBeanDefinitionReader(factory);
	//XmlBeanDefinitionReader 执行载入 BeanDefinition 的方法,最后会完成 Bean 的载入和注册。完成后 Bean 就成功
	的放置到 IOC 容器当中,以后我们就可以从中取得 Bean 来使用
	reader.loadBeanDefinitions(resource);

实际调用入口 refresh()
在这里插入图片描述
接下来展开诸多细节,
AbstractApplicationContext 的 refresh 函数载入 Bean 定义过程

refresh()方法的作用是:在创建 IOC 容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在 refresh 之后使用的是新建立起来的 IOC 容器。refresh 的作用类似于对 IOC 容器的重启,

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
	//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
	prepareRefresh();
	//告诉子类启动 refreshBeanFactory()方法,Bean 定义资源文件的载入从子类的 refreshBeanFactory()方法启动
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
	//为 BeanFactory 配置容器特性,例如类加载器、事件处理器等
	prepareBeanFactory(beanFactory);
	try {
			//为容器的某些子类指定特殊的 BeanPost 事件处理器
			postProcessBeanFactory(beanFactory);
			//调用所有注册的 BeanFactoryPostProcessor 的 Bean
			invokeBeanFactoryPostProcessors(beanFactory);
			//为 BeanFactory 注册 BeanPost 事件处理器.BeanPostProcessor 是 Bean 后置处理器,用于监听容器触发的事件
			registerBeanPostProcessors(beanFactory);
			//初始化信息源,和国际化相关.
			initMessageSource();
			//初始化容器事件传播器.
			initApplicationEventMulticaster();
			//调用子类的某些特殊 Bean 初始化方法
			onRefresh();
			//为事件传播器注册事件监听器.
			registerListeners();
			//初始化所有剩余的单例 Bean.
			finishBeanFactoryInitialization(beanFactory);
			//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
			finishRefresh();
		} catch (BeansException ex) {
			//销毁以创建的单态 Bean
			destroyBeans();
			//取消 refresh 操作,重置容器的同步标识.
			cancelRefresh(ex);
		throw ex;
	}
}

装配bean的过程中会出现一个问题:A依赖B,装配A的时候B的实例还没有创建,怎么办?

spring解决这个问题的办法是:先创建B对象,装配好bean,然后把B注入A,继续完成A的装配.
假设:当 Bean_A 依赖着 Bean_B,而这个 Bean_A 在加载的时候,其配置的 ref = “Bean_B” 在解析的时候只是一个占位符,被放入了 Bean_A 的属性集合中,当调用 getBean 时,需要真正 Bean_B 注入到 Bean_A 内部时,就需要从容器中获取这个 Bean_B,因此产生了递归。

为什么不是在加载的时候,就直接注入呢?
因为加载的顺序不同,很可能 Bean_A 依赖的 Bean_B 还没有加载好,也就无法从容器中获取,你不能要求用户把 Bean 的加载顺序排列好,这是不人道的

Spring 的IoC。将其分为了 2 个步骤:
	加载所有的 Bean 配置成 BeanDefinition 到容器中,如果 Bean 有依赖关系,则使用占位符暂时代替。然后,在调用 getBean 的时候,进行真正的依赖注入,即如果碰到了属性是 ref 的(占位符),那么就从容器里获取这个 Bean,然后注入到实例中 —— 称之为依赖注入。

那么spring Aop如何实现的呢,其实是对对象进行包装~使其成为代理对象、这是一个可以invoke的对象
猜想一下,1、对普通bean包装 2、wrapper存到map中 3、切点可配置
在这里插入图片描述
getbean()

具体如何手写spring请前往

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值