spring
2021-06-01 16:17:34 0 举报
spring原理
作者其他创作
大纲/内容
个人信息<br>
什么是spring<br>
spring是一个整合框架,给我们带来春天的感觉。
300行代码实现<br>
加载配置文件<br>
扫描相关的类<br>
讲扫描到的类放入ioc容器<br>
1、循环扫描到的类<br>2、通过类的全类路径名获取反射对象<br>3、如果类加了注解,将类放入容器ioc.put(beanName,instance);<br>
完成依赖注入<br>
利用反射机制给属性赋值<br>1、获取属性名(如果没有自定义beanname,默认根据类型注入)<br>2、反射暴力访问属性<br>3、用反射机制给字段动态赋值field.set( ,ioc.get(beanName) )<br>
初始化HandlerMapping<br>
初始化url和Method一对一关系<br>hanglerMapping.put(url,method);<br>
AOP<br>
流程<br>
BeanPostProcessor后置处理器<br>
分支主题
IOC<br>
控制反转 将对象的创建交给ioc容器<br>将<font color="#f15a23">扫描包下</font>添加<font color="#c41230">注解的类</font> 通过反射 将对象注入到ioc容器<br>
核心容器<br>
BeanFactory<br>
定义ioc容器的基本行为<br>只关系能从工厂得到什么产品,不关心工厂是怎么生产这些产品<br>要知道怎么生产产品,看具体ioc的实现<br>
BeanDefinition<br>
BeanDefinitionReader<br>
对spring配置文件进行解析<br>
DispatcherServlet<br>
子主题
流程<br>
加载配置文件<br>
将xml中的bean换成beanDefinition
扫描配置文件的包下的类(注解才需要),将注解转换成beanDefinition<br>
会根据过滤规则找到注解,spring默认的过滤规则需实现@component<br>可自定义过滤器 @某某自定义注解(includeFilters = )<br>
在IOC容器中注册<br>
容器解析得到beanDefinition后,内部维护一HashMa来保存BeanDefinition<br>
DI<br>
依赖注入<br>对象是被动接受依赖类,而不是自己主动去找。<font color="#c41230">在容器实例化对象的时候主动将他依赖的类注入给它</font><br> 将<font color="#f15a23">扫描包下</font>添加注解类的<font color="#f15a23">添加注解的属性</font> 注入对象(从ioc容器获取对象) 完成属性实例化<br>
流程<br>
获取IOC容器中的bean getBean(String name)
AbstructBeanFactory<br>
1)实例化阶段<br>
循环读取BeanDefinition的缓存信息,<br>调用getBean从BeanDefinition获取对象实例<br>封装成BeanWrapper对象,<br>添加到ioc容器<br>
AbstructBeanFactory
2)依赖注入阶段
循环IOC容器执行以来注入
事务<br>
解决数据操作带来的完整性和一致性问题。
特性<br>
原子性(Automicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要 么都做,要么都不做。
一致性(Consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。 一致性与原子性是密切相关的。
隔离性(Isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及 使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(Durability)。持久性也称永久性(Permanence),指一个事务一旦提交,它 对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何 影响。
隔离级别<br>
隔离级别:<font color="#f15a23">隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能影响也越大。</font>
级别<br>
READ COMMITTED Read Committed 读取提交内容<br>大多数数据库系统的默认隔离级别(但是不是MySQL的默认隔离级别),满足了隔离的早先简单定义:一个事务开始时,只能“看见”已经提交事务所做的改变,一个事务从开始到提交前,所做的任何数据改变都是不可见的,除非已经提交。这种隔离级别也支持所谓的“不可重复读”。这意味着用户运行同一个语句两次,看到的结果是不同的。<br>
READ UNCOMMITTED Read UnCommitted 读取未提交内容在这个隔离级别,所有事务都可以“看到”未提交事务的执行结果。在这种级别上,可能会产生很多问题,除非用户真的知道自己在做什么,并有很好的理由选择这样做。本隔离级别很少用于实际应用,因为它的性能也不必其他性能好多少,而别的级别还有其他更多的优点。读取未提交数据,也被称为“脏读”
<br>
REPEATABLE READ Repeatable Read 可重复读MySQL数据库默认的隔离级别。该级别解决了READ UNCOMMITTED隔离级别导致的问题。它保证同一事务的多个实例在并发读取事务时,会“看到同样的”数据行。不过,这会导致另外一个棘手问题“幻读”。InnoDB和Falcon存储引擎通过多版本并发控制机制解决了幻读问题。
SERIALIZABLE Serializable 可串行化该级别是最高级别的隔离级。它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简而言之,SERIALIZABLE是在每个读的数据行上加锁。在这个级别,可能导致大量的超时Timeout和锁竞争Lock Contention现象,实际应用中很少使用到这个级别,但如果用户的应用为了数据的稳定性,需要强制减少并发的话,也可以选择这种隔离级
导致的问题<br>
子主题
脏读,不可重复读,幻读
<br>脏读:事务1对数据进行了增删改,但未提交,事务2可以读取到事务1未提交的数据。如果事务1回滚,那么事务2就读取到了脏数据。<br>不可重复读:事务1进行两次读操作,第一次读操作和第二次读操作之间,事务2对数据进行了修改,导致事务1两次读取不一致。<br>幻读:事务1进行两次读操作,第一次读操作和第二次读操作之间, 事务2 插入了相同搜索条件的新数据,事务1再次按照原先条件进行读取时,发现了事务2 新插入的数据 称为幻读<br><font color="#f15a23">不可重复读注重的是值是否相等,幻读注重的是条数</font>
spring事务的传播属性<br>
子主题
传播机制<br>
Spring事务机制主要包括声明式事务和编程式事务,此处侧重讲解声明式事务,编程式事务在实际开发中得不到广泛使用,仅供学习参考。
spring在TransactionDefinition接口中定义了七个事务传播行为:
propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。<br>propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。<br>propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。<br>propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。<br>propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。<br>propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。<br>propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作<br>
事务的嵌套<br>
子主题
循环依赖<br>
A依赖B,B依赖A 形成依赖闭环<br>IOC容器对bean的初始化根据BeanDefinition循环迭代,有一定的顺序。在执行依赖注入时,需要自动赋值的属性对应的对象有可能还没初始化,没初始化也就没有对应的实例注入。<br>
三级缓存
一级缓存singletonObjects
用于保存实例化、注入、初始化完成的bean实例
二级缓存earlySingletonObjects
用于保存实例化完成的bean实例
三级缓存singletonFactories
用于保存bean创建工厂,以便于后面扩展有机会创建代理对象
子主题
流程<br>
先从一级缓存里拿<br>
如果一级缓存中没有 但有创建标志 说明是循环依赖<br>
如果二级缓存中也没有 那就从三级缓存中拿<br>
将创建出来的对象重新放入二级缓存中<br>
子主题
<br>
<br>
interview<br>
收集<br>
1.spring中的bean是线程安全的吗?为什么?<br>
答:spring中的bean是否线程安全与spring无关,因为spring只承担了创建和管理bean的职责,并没有对bean进行任何修改。spring中的bean是自己创建的。
2.Spring IOC和DI的工作原理并用自己的语言描述出来。<br>
答:<br>Spring IOC的基本流程1)读取配置文件2)解析配置文件,并封装成BeanDefinition3) 把BeanDefinition对应的实例放入到容器进行缓存<br>Spring DI的基本流程1)循环读取BeanDefinition的缓存信息2)调用getBean()方法创建对象实例3)将创建好的对象实例包装为BeanWrapper4)将BeanWrapper对象缓存到IOC容器5)循环IOC容器执行以来注入<br>
3.手绘Spring IOC和DI部分的类结构图
答:<br>BeanDefinition保存每个bean配置的解析结果<br>BeanWapper 保存原始对象和原始对象的class<br>ApplicationContext Spring 中最核心的IOC工厂,也是Spring的主入口<br>其中BeanDefinition、BeanWapper和ApplicationContext三者的关系如下图所示:<br>
子主题
1.spring是什么?
1)简化开发,解放双手<br>2)spring框架是粘合剂,将其他框架完美的粘合起来
IOC与DI?
IOC: 控制反转,将类的对象的创建交给Spring类管理创建. ioc改善了模块之间的耦合问题<br>DI: 依赖注入,将类里面的属性在创建类的过程中给属性赋值. <br>DI和IOC的关系: DI不能单独存在,DI需要在IOC的基础上来完成.<br>依赖注入是控制反转的基础
spring bean的生命周期?
所谓生命周期,从创建到调用到销毁的一个过程。Spring bean factory负责管理在spring容器中 被创建的bean的生命周期。<br><font color="#c41230">对象创建</font><br>1)从xml或注解@Bean或Java代码BeanDefinitionBuilder中<font color="#f1753f">读取Bean的定义</font>,<br>2)<font color="#f15a23">实例化Bean对象</font> Bean的实例化是使用反射实现的。<br>3)<font color="#f1753f">设置Bean属性</font> Bean实例化完成后,利用反射技术实现属性及依赖Bean的注入。<br>【Bean生命周期要经历很多阶段,但这些阶段大部分都是可选的<br>4)BeanNameAware的setBeanName()方法:如果某个Bean实现了BeanNameAware接口,那么Spring将会将Bean实例的ID传递给setBeanName()方法,在Bean类中新增一个beanName字段,并实现setBeanName()方法。<br>(5)BeanFactoryAware的setBeanFactory()方法:如果某个Bean实现了BeanFactoryAware接口,那么Spring将会将创建Bean的BeanFactory传递给setBeanFactory()方法,在Bean类中新增了一个beanFactory字段用来保存BeanFactory的值,并实现setBeanFactory()方法。<br>(6)ApplicationContextAware的setApplicationContext()方法:如果某个Bean实现了ApplicationContextAware接口,那么Spring将会将该Bean所在的上下文环境ApplicationContext传递给setApplicationContext()方法,在Bean类中新增一个ApplicationContext字段用来保存ApplicationContext的值,并实现setApplicationContext()方法。<br>(7)BeanPostProcessor预初始化方法:如果某个IoC容器中增加的实现BeanPostProcessor接口的实现类Bean,那么在该容器中实例化Bean之后,执行初始化之前会调用BeanPostProcessor中的postProcessBeforeInitialization()方法执行预初始化处理。<br>(8)InitializingBean的afterPropertiesSet()方法:如果Bean实现了InitializingBean接口,那么Bean在实例化完成后将会执行接口中的afterPropertiesSet()方法来进行初始化。<br>(9)自定义的inti-method指定的方法:如果配置文件中使用init-method属性指定了初始化方法,那么Bean在实例化完成后将会调用该属性指定的初始化方法进行Bean的初始化。<br>(10)BeanPostProcessor初始化后方法:如果某个IoC容器中增加的实现BeanPostProcessor接口的实现类Bean,那么在该容器中实例化Bean之后并且完成初始化调用后执行该接口中的postProcessorAfterInitialization()方法进行初始化后处理。<br>】<br>(11)使用Bean:此时有关Bean的所有准备工作均已完成,Bean可以被程序使用了,它们将会一直驻留在应用上下文中,直到该上下文环境被销毁。<br><font color="#f15a23">对象销毁</font><br>(12)DisposableBean的destory()方法:如果Bean实现了DisposableBean接口,Spring将会在Bean实例销毁之前调用该接口的destory()方法,来完成一些销毁之前的处理工作。<br>(13)自定义的destory-method指定的方法:如果在配置文件中使用destory-method指定了销毁方法,那么在Bean实例销毁之前会调用该指定的方法完成一些销毁之前的处理工作。<br><br>singleton 从spring容器启动到spring容器的销毁,如果是延时加载,在调用前创建对象<br>prototype 在调用前创建,调用后销毁<br>作用域决定了生命周期的长短
spring bean各作用域之间的区别?
1)singleton 作用域全局,默认的bean范围,不管接受到多少个请求,每个容器中只会创建一个bean实例,单例模式由bean自身来维护。<br>2)prototype 全局的,与单例范围相反,为每一个bean请求提供一个实例<br>3)request 在一次请求发起和结束之间 请求结束bean失效并被垃圾收集器回收<br>4)session 在一个session创建和session失效之间,有效期配置一般默认是30分钟<br>5)global-session 全局会话,所有会话共享一个实例。
.spring中的bean是线程安全的吗?
线程安全这个问题,要从单例与原型Bean分别进行说明。<br><font color="#f15a23">原型Bean</font><br>对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。<br><font color="#f15a23">单例Bean</font> Spring中的Bean默认是单例模式的,框架并没有对bean进行多线程的封装处理<br>对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。<br>如果单例Bean,是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。<br>对于有状态的bean,Spring官方提供的bean,一般提供了通过ThreadLocal去解决线程安全的方法,比如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等。<br>注: Spring容器本身并没有提供线程安全的策略,因此是否线程安全完全取决于Bean本身的特性。<br>有状态就是有数据存储功能<br>无状态就是不会保存数据
请问spring中用到了哪些设计模式
<br>工厂模式、单例、原型、代理、享元模式、<br>门面模式、适配器、委派、装饰器、责任链、<br>空对象模式、解释器、<br>1、代理模式—在AOP和remoting中被用的 比较多。<br>2、单例模式:在spring 配置文件中定义的 bean默认为单例模式。<br>3、模板梩式:用来解决代码重复的问题。<br>比如.RestTemplate, JmsTemplate, JpaTemplate。<br>4、委派模式:Srping提供了DispatcherServlet来对清求进行分发。<br>5、工厂摆式:BeanFactory 用来创建对象的实例,贵穿千BeanFactory / ApplicationContext接口的核心理念。<br>6、代理模式:AOP思想的底层实现技术,Spring中采用丿DK Proxy和Cglib类库。
与springboot区别<br>
子主题
spring事务怎么传播?
TransationManager,代理模式<br>pool<br><br>execute()原是逻辑,拿到的是Datasource connection对象
BeanFactory和FactoryBean的区别?<br>详情看链接https://note.youdao.com/s/bvCT4rEO
BeanFactory:BeanFactory 是ioc容器的底层实现接口,是ApplicationContext 顶级接口<br>spring不允许我们直接操作 BeanFactory bean工厂,所以为我们提供了ApplicationContext 这个接口 此接口集成BeanFactory 接口,ApplicationContext包含BeanFactory的所有功能,同时还进行更多的扩展。<br><br>BeanFactory 接口又衍生出以下接口,其中我们经常用到的是ApplicationContext 接口
ApplicationContext 继承图
子主题
FactoryBean:FactoryBean 是spirng提供的工厂bean的一个接口<br>FactoryBean 接口提供三个方法,用来创建对象,<br>FactoryBean 具体返回的对象是由getObject 方法决定的。
<font color="#f15a23">BeanFactory</font>是个bean 工厂,是一个工厂类(接口), 它负责生产和管理bean的一个工厂<br>是ioc 容器最底层的接口,是个ioc容器,是spring用来管理和装配普通bean的ioc容器(这些bean成为普通bean)。<br><font color="#f15a23">FactoryBean</font>是个bean,在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,是一个可以生产对象和装饰对象的工厂bean,由spring管理后,生产的对象是由getObject()方法决定的(从容器中获取到的对象不是<br>“ FactoryBeanTest ” 对象)。
项目中如何应用AOP?
生命式事务管理、日志监听、权限管理、安全监控。。。
一个方法内,for循环内重复操作数据库?
如果循环不可控,千万千万不要在一个方法内for循环去查询数据库,因为会多次连接数据库,导致连接池的数量不可控。<br>解决方案:1)分页(可控,每页连接可控) 2)缓存 3)联合查询
请解释各种自动装配模式的区别?
在Spring框架中共有5种自动装配<br>1. no:这是Spring框架的默认设置,在该设置下 自动装配是关闭的,开发者需要自行在bean 定义中用标签明确的设置依赖关系。<br>2.byName:该选项可以根据bean 名称设置依赖关系。 当向1个bean 中自动装配个属性时,容器将根据bean的名称自动在在配置文件中查询1个匹配的bean。 如果找到的话,就装配这个属性,如果没找到的话就报错。<br>3.byType:该选项可以根据bean类型设置依赖关系。 当向1个bean中自动装配1个属性时,容器将根据bean的类型自动在在配置文件 中查询1个匹配的bean。 如果找到的话,就装配这个属性,如果没找到的话就报错。<br>4.constructor:迼器的自动装配和byType模式类似,但是仅仅适用千与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型1致的bean,那么将会抛出异常。<br>5.autodetect :该模式自动探则使用构造器自动装配或者byType自动装配 。 首先,首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式 。
请解释下 Spring 框架中的 IOC容器?
Spring中的org.springfra mework.bea ns 包和org.springfra mewo rk.co ntext包构成了Spring框架IOC容器的基础。<br>Bean Factory 接口提供了1个先进的配置 机制,使得任何类型的对象的配置成为可能 。App Ii cati onContex接口对BeanFactory (是1个子接口)进行了扩展,在BeanFactory的基础上添加了其他功能,比如与Spring的AOP更容男集成,也提供了处理 message resource的机制(用于国际化)事件传播以及应用层的特别配置,比如针对Web应用的Web ApplicationContext。
在Spring 中可以注入 null 或空字符串吗?<br>
完全可以。
0 条评论
下一页