-
为什么要使用spring
- 有ioc和aop
- 提供事务支持
- 入侵小,与很多框架都可以集成
Origin 运行跨域,并且在拦截器中放行option请求
-
使用netty代理
-
设计模式
-
为什么要使用spring
- 有ioc和aop
- 提供事务支持
- 入侵小,与很多框架都可以集成
-
spring是什么:spring是一个轻量级开源框架,解决企业开发的复杂性(pojo的轻量性和入侵性小、ioc和aop)
-
aop的理解:众所周知,程序是由多个模块组成,在模块中核心时业务代码,aop用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,减少系统中的重复代码,降低了模块间的耦合度,提高系统的可维护性。(Aop可以对某个对象或某个对象的功能进行增强,比如对象中的方法进行增强,可以在执行某个方法之前额外的做一些事情,在执行某个方法之后额外的做一些事情)
-
aop几个概念名称:切面、切点、连接点、通知、目标对象、织入、引入。
-
Spring 通知有哪几个:执行方法前通知、执行方法完成后通知(不论是正常返回还是异常退出)、环绕通知、返回后通知(在连接点正常完成后执行的通知(如果连接点抛出异常,则不执行))、抛出异常后通知
-
ioc的理解:ioc容器、控制反转、依赖注入
- ioc容器:实际就是一个map,里面存储这各种对象,在项目启动的时候会读取配置文件里面的bean节点,根据全限定类名使用反射创建对象反射放到map里。这时候map里面就有各种对象,接下来我们代码中需要用到里面的对象时,再通过DI注入(@Autowried、resource、xxx)
- 控制反转:
- 在没有引入ioc容器之前,A对象需要依赖于B对象,那么对象A在初始化或者在运行到某点的时候,自己必须去创建对象B或者使用已创建的对象B、创建B的控制权都在自己手上。
- 引入ioc后,对象A和对象B之间失去了直接联系,当对象A运行到需要对象B的时候,ioc容器会主动一个对象注入到对象A需要的地方。结论:控制权颠覆过来,这就是 ” 控制反转 “
- 依赖注入(DI):依赖注入时实现ioc的方法:就是有ioc容器在运行期间,动态地将某种依赖关系注入到对象之中(这是一种思想)。
-
BeanFactory和ApplicationContext区别
- ApplicationContext是BeanFactory子接口(继承),ApplicationContext提供了更完整的功能:*继承了MessageSource,支持国际化。*统一的资源文件访问方式。*提供在监听器中注册bean事件。*同时加载多个配置文件。载入多个(有继承关系)上下文,使得每个上下文都专注于一个特点的层次。
- BeanFactory采用的是延迟加载形式注入bean的,即只有在使用到某个bean时(getBean),才对该bean进行加载实例化。这样,我们就不能发现一些存在的spring的配置问题,如果Bean的某个属性没有注入,BeanFactory加载后,直至第一次使用调用getBean方法才会抛出异常。
- ApplicationContext:它是在容器启动时,一次性创建了所有Bean。在容器启动时,我们就可以发现Spring中存在的配置错误。
- 相对于基本BeanFactory,ApplicationContext唯一的不足是占用内存空间,当应用程序的Bean比较多时,程序启动会比较慢,但是启动后程序还是很快的。
- BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建。
- BeanFactory和ApplicationContext都支持BeanPostProcessor,BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。
-
Spring Bean的生命周期
实例化->属性赋值->初始化->销毁
Spring容器初始化
【步骤1】执行Bean的无参构造函数
【步骤2】执行Bean的set方法,设置name属性值:coolsummermoon
【步骤2】执行Bean的set方法,设置sex属性值:man
【步骤3】执行BeanNameAware中setBeanName方法,beanName值:iocBeanLifeService
【步骤4】执行BeanClassLoaderAware中setBeanClassLoader,ClassLoader的name = sun.misc.Launcher$AppClassLoader
【步骤5】执行BeanFactoryAware中setBeanFactory,beanFactory中是否包含IocBeanLifeService:true
【步骤6】执行EnvironmentAware的setEnvironment方法
【步骤7】执行ResourceLoaderAware的setResourceLoader方法,Resource File Name=applicationContext.xml
【步骤8】执行ApplicationEventPublisherAware中setApplicationEventPublisher方法
【步骤9】执行ApplicationContextAware的setApplicationContext方法,Bean Definition Names=[iocBeanLifeService, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0, ioc.CustomerBeanPostProcessor#0]
【步骤10】执行BeanPostProcessor中postProcessBeforeInitialization方法,beanName=iocBeanLifeService
【步骤11】执行PostConstruct注解标注的方法
【步骤12】执行InitializingBean的afterPropertiesSet方法
【步骤13】执行配置的init-method
【步骤14】执行BeanPostProcessor的postProcessAfterInitialization方法,beanName=iocBeanLifeService
Spring容器初始化完毕========================
从容器中获取Bean
IocBeanLifeService{name='coolsummermoon', sex='man'}
Spring容器准备关闭==========================
【步骤15】执行preDestroy注解标注的方法
【步骤16】执行DisposableBean接口的destroy方法
【步骤17】执行配置的destroy-method
Spring容器完成关闭===========================
- Spring支持的几种bean的作用域
- singleton:默认,每个容器只有一个bean的实例,单例的模式由BeanFactory自身来维护。该对象的生命周期是与Spring IOC容器一致(但在第一次被注入时才会创建)。
- prototype:为每个bean请求提供一个实例,在每次注入时都会创建一个新的对象。
- request:bean定义为每个Http请求中创建一个实例,也就是说在单个请求中都会复用这一个单例对象,在请求完成以后,bean会失效并被垃圾回收器回收。
- session:与request范围类似,同一个session会话共享一个实例,不同会话使用不同的实例。
- global-session:全局作用域,global-session和protlet应用相关。所有会话共享一个实例。
- spring框架中的单例Bean时线程安全的么:spring中的Bean默认是单例的,框架并没有对bean进行多线程的封装处理。如果bean是有状态(就是有数据存储功能),那么就需要开发人员自己来进行线程安全保证,如果没有状态,那么bean便是安全的。最简单的办法就是将他的作用域改为prototype,这样便保证了线程安全。
- Spring基于xml注入bean的几种方式:
- Spring框架中都用到了那些设计模式
- 简单工厂:
- 工方法:
- 单例模式:
- 适配器模式:
- 装饰器模式:
- 动态代理:
- 策略模式:
- 观察者模式:
- Spring事务的实现方式和原理以及隔离级别
- 事务几种实现方式:
- 编程式事务
- 声明式事务管理(基于 @Transactional 的声明式事务管理,基于Aspectj AOP配置事务,TransactionProxyFactoryBean的声明式事务管理)
- spring事务管理是基于数据库本身的事务处理机制进行扩展、事务具备的四个特性:原子性、一致性、隔离性、持久性。
- 原子性:事务最基本的操作单元,要么全部成功,要么全部失败,事务在执行过程中出现错误,回滚到事务开始前的状态,就像事务从来没有执行国一样。
- 一致性:执行前和执行后数据库必须处于一致性状态:如果事务成功,那么全部的数据必须正确的变化。如果事务出错,事务回滚,并且系统回到执行之前的状态。
- 隔离性:在并发的环境中,不同的事务同时操作相同的数据,每个事物都有各自的完整数据空间。
- 持久性:事务结束后,数据库所做的更新就会永久保下来
- 事务的传播特性:
- 事务的隔离级别:
- read uncommited:未提交读 它允许另外一个事务可以看到这个事务未提交的数据。
- read commited:已提交读 保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。
- repeatable read:可重复读 这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。
- serializable:串行读 这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读
- 脏读、幻读、不可重复读概念
- 脏读:指当一个事务正字访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。
- 不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。
- 幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)
- 事务几种实现方式: