一、Spring简介
1.1 spring的七个模块

(1)Spring Core:
Core封装包是框架的最基础部分,提供IOC和依赖注入特性。这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
(2)Spring Context:
构建于Core封装包基础上的 Context封装包,提供了一种框架式的对象访问方法,有些象JNDI注册器。Context封装包的特性得自于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明创建,比如说通过Servlet容器。
(3)Spring DAO:
DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs(plain old Java objects)都适用。
(4)Spring ORM:
ORM封装包提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、hibernate 和 iBatis 。利用ORM封装包,可以混合使用所有spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。
(5)Spring AOP:
Spring的 AOP 封装包提供了符合AOP Alliance规范的面向方面的编程实现,让你可以定义,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。而且,利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中。
(6)Spring Web:
Spring中的 Web 包提供了基础的针对Web开发的集成特性,例如多方文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。
(7)Spring Web MVC:
Spring中的MVC封装包提供了Web应用的Model-View-Controller(MVC)实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和Web Form之间。并且,还可以借助Spring框架的其他特性。
1.2 spring的作用
(1)简化企业级开发
①封装了大部分的企业级服务,提供了更好的访问这些服务的方式
②提供了IOC,AOP功能的容器,方便编程
(2)遵循Spring框架的应用程序,一定是设计良好的,针对接口编程,这样就简化了企业级程序的设计。
(3) Spring的组成
① Spring Core:核心容器,BeanFactory提供了组件生命周期的管理,组件的创建,装配,销毁等功能
SpringContext:ApplicationContext,扩展核心容器,提供事件处理、国际化等功能。它提供了一些企业级服务的功能,提供了JNDI,EJB,RMI的支持。
② Spring AOP:提供切面支持
③ Spring DAO:提供事务支持,JDBC,DAO支持
④ Spring ORM:对流行的O/R Mapping封装或支持
⑤ Spring Web:提供Web应用上下文,对Web开发提供功能上的支持,如请求,表单,异常等。
⑥ Spring Web MVC:全功能MVC框架,作用等同于Struts。
1.3 Spring的优点
答:1.降低了组件之间的耦合性,实现了软件各层之间的解耦
2.可以使用容易提供的众多服务,如事务管理,消息服务等
3.容器提供单例模式支持
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
5.容器提供了众多的辅助类,能加快应用的开发
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等 7.spring属于低侵入式设计,代码的污染极低
8.独立于各种应用服务器
9.spring的DI机制降低了业务对象替换的复杂性
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring 的部分或全部

二、Spring依赖注入和SpringIOC
2.1注入的三种方式
使用构造器注入
使用属性setter方法注入
使用Field注入(用于注解方式)
2.2 IoC容器的概念
IoC容器就是具有依赖注入功能的容器,IoC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IoC容器进行组装。在Spring中BeanFactory是IoC容器的实际代表者。
Spring IoC容器如何知道哪些是它管理的对象呢?这就需要配置文件,Spring IoC容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配。一般使用基于xml配置文件进行配置元数据,而且Spring与配置文件完全解耦的,可以使用其他任何可能的方式进行配置元数据,比如注解、基于java文件的、基于属性文件的配置都可以。
2.3 IoC容器详解
在Spring Ioc容器的代表就是org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了IoC容器最基本功能;而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成、国际化处理、事件传播及提供不同层次的context实现 (如针对web应用的WebApplicationContext)。简单说, BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。

2.4 IoC容器的两种方式
方法一:
在类路径下寻找配置文件来实例化容器
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
方法二:
在文件系统路径下寻找配置文件来实例化容器
ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{“d:\\beans.xml“});
2.5 bean生命周期
创建(实例化-初始化)-使用-销毁

参考博客:
https://blog.csdn.net/a327369238/article/details/52193822
2.6 bean实例化方式
[if !supportLists](1)[endif]构造器创建Bean实例
[if !supportLists](2)[endif]静态工厂方法创建bean
[if !supportLists](3)[endif]调用实例工厂创建bean
2.7 bean作用域
Spring容器中的bean可以分为5个范围。所有范围的名称都是自说明的,但是为了避免混淆,还是让我们来解释一下:
singleton:这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例,单例的模式由bean factory自身来维护。
prototype:原形范围与单例范围相反,为每一个bean请求提供一个实例。
request:在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
Session:与请求范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。
全局作用域与Servlet中的session作用域效果相同。
2.8 bean之间的关系
继承:
在面向对象的编程原理中,当多个类拥有相同的方法和属性时,则能引入父类使用于消除重复的代码。而在Spring容器中,假如多个 Bean 存在相同的配置信息,我们能定义一个父 Bean ,这样子 Bean 将会自动继承父 Bean 的配置信息 。
依赖:
一般情况下,用来建立 Bean 之间的依赖关系, Spring 容器负责管理这些关系,当实例化一个 Bean 时,容器保证该 Bean 所依赖的 Bean 都已经完成了初始化工作。
但在某些情况下,Bean之间的依赖关系并没有那么显著。
引使用ID:
假设一个Bean需要引使用另一个 Bean 的 id 值(beanName),这一般使用于在运行期间在 Bean 中通过 getBean(beanName) 方法获取另一个 Bean 的情境。
2.9 bean后处理器
Spring提供了两种常用的后处理器:
Bean后处理器: 这种后处理器会对容器中Bean进行后处理,对Bean进行额外加强;
容器后处理器:这种后处理器会对IoC容器进行后处理,用于增强容器功能。
Bean后处理器:
Bean后处理器是一种特殊的Bean,这种特殊的Bean并不对外提供服务,它甚至可以无须id属性,它主要负责对容器中的其他Bean执行后处理,例如为容器中的目标Bean生成代理等,这种Bean称为Bean后处理器。Bean后处理器会在Bean实例创建成功之后,对Bean实例进行进一步的增强处理。Bean后处理器必须实现BeanPostProcessor接口,同时必须实现该接口的两个方法。
容器后处理器:
Bean后处理器负责处理容器中的所有Bean实例,而容器后处理器则负责处理容器本身。容器后处理器必须实现BeanFactoryPostProcessor接口,并实现该接口的一个方法postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)实现该方法的方法体就是对Spring容器进行的处理,这种处理可以对Spring容器进行自定义扩展,当然也可以对Spring容器不进行任何处理。
四、Spring的AOP
4.1 AOP是什么
定义:将程序中的交叉业务逻辑提取出来,称之为切面。将这些切面动态织入到目标对象,然后生成一个代理对象的过程。
4.2 AOP核心概念
(1)Aspect(切面)
切面,是对交叉业务逻辑的统称。
(2)Joinpoint(连接点)
连接点,指切面可以织入到目标对象的位置(方法,属性等)。
(3)Advice(通知)
通知,指切面的具体实现。
(4)Pointcut(切入点)
切入点,指通知应用到哪些类的哪些方法或属性之上的规则。
(5)Introduction(引入)
引入,指动态地给一个对象增加方法或属性的一种特殊的通知。
(6)Weaving(织入)
织入,指将通知插入到目标对象。
(7)Target(目标对象)
目标对象,指需要织入切面的对象。
(8)Proxy(代理对象)
代理对象,指切面织入目标对象之后形成的对象。
4.3 AOP原理
采用动态代理模式。
Spring AOP采用动态代理的过程:
(1)将切面使用动态代理的方式动态织入到目标对象(被代理类),形成一个代理对象;
(2)目标对象如果没有实现代理接口,那么Spring会采用CGLib来生成代理对象,该代理对象是目标对象的子类;
(3)目标对象如果是final类,并且也没实现代理接口,就不能运用AOP。
4.4 AOP通知
(1)前置通知@Before:前置通知通过@Before注解进行标注,并可直接传入切点表达式的值,该通知在目标函数执行前执行,注意JoinPoint,是Spring提供的静态变量,通过joinPoint 参数,可以获取目标对象的信息,如类名称,方法参数,方法名称等,,该参数是可选的。
(2)后置通知@AfterReturning?:通过@AfterReturning注解进行标注,该函数在目标函数执行完成后执行,并可以获取到目标函数最终的返回值returnVal,当目标函数没有返回值时,returnVal将返回null,必须通过returning = “returnVal”注明参数的名称而且必须与通知函数的参数名称相同。请注意,在任何通知中这些参数都是可选的,需要使用时直接填写即可,不需要使用时,可以完成不用声明出来。
(3)异常通知 @AfterThrowing:该通知只有在异常时才会被触发,并由throwing来声明一个接收异常信息的变量,同样异常通知也用于Joinpoint参数,需要时加上即可
(4)最终通知 @After:该通知有点类似于finally代码块,只要应用了无论什么情况下都会执行。
(5)环绕通知@Around?:环绕通知既可以在目标方法前执行也可在目标方法之后执行,更重要的是环绕通知可以控制目标方法是否指向执行,但即使如此,我们应该尽量以最简单的方式满足需求,在仅需在目标方法前执行时,应该采用前置通知而非环绕通知。案例代码如下第一个参数必须是ProceedingJoinPoint,通过该对象的proceed()方法来执行目标函数,proceed()的返回值就是环绕通知的返回值。同样的,ProceedingJoinPoint对象也是可以获取目标对象的信息,如类名称,方法参数,方法名称等等。
4.5 AOP配置的两种方式
(1)基于注解
Before("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
定义切入点函数:

(2)AOP配置的两种方式-基于XML
(3)AOP配置的两种方式-使用工厂模式配置
参考文章:
https://blog.csdn.net/kpp19920121/article/details/51933397
五、Spring有两种代理方式:
答: 若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。
优点:因为有接口,所以使系统更加松耦合
缺点:为每一个目标类创建接口
若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
优点:因为代理类与目标类是继承关系,所以不需要有接口的存在。
缺点:因为没有使用接口,所以系统的耦合性没有使用JDK的动态代理好。
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
5.1 JDK动态代理
此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑。
代理模式在实际使用时需要指定具体的目标对象,如果为每个类都添加一个代理类的话,会导致类很多,同时如果不知道具体类的话,怎样实现代理模式呢?这就引出动态代理。
动态代理的步骤:
(1)通过实现InvocationHandler接口创建自己的调用处理器
(2)通过为proxy类指定了ClassLoader对象和一组interface来创建动态代理类
(3)通过反射机制获得动态代理类的构造函数,其唯一参数是调用处理器接口类型
(4)通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入
5.2 CGLIB代理
CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的所有方法,所以该类或方法不能声明称final的。
如果目标对象没有实现接口,则默认会采用CGLIB代理;
如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。
六、Spring的事务
6.1 Spring如何解决事务隔离级别:
(1)TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是
(2)TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
(3)TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
(4)TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
(5)TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别
6.2 Spring如何解决事务传播行为:
(1)TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
(2)TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
(3)TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
(4)TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
(5)TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
(6)TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
(7)TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
详情参考博客:
http://blog.csdn.net/pml18710973036/article/details/58607148
https://blog.csdn.net/bao19901210/article/details/41724355
6.3配置事务的5种方式
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

第一种方式:每个Bean都有一个代理
第二种方式:所有Bean共享一个代理基类
第三种方式:使用拦截器
第四种方式:使用tx标签配置的拦截器
第五种方式:全注解
参考文章:
http://www.jb51.net/article/111688.htm?&_=1524383494677
七、Spring5.0新特性
JDK基线更新
核心框架修正
核心容器更新
含Kotlin在内的函数式编程
响应式编程模型
测试改进
库支持
中止支持
SpringFramework5.0的JDK基线更新