1、Spring是什么?
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
https://xueqiu.com/6556660064...
Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目标是用于简化企业应用程序的开发,它使得开发者只须要关怀业务需要。次要包含以下七个模块:
- Spring Context:提供框架式的Bean拜访形式,以及企业级性能(JNDI、定时工作等);
- Spring Core:外围类库,所有性能都依赖于该类库,提供IOC和DI服务;
- Spring AOP:AOP服务;
- Spring Web:提供了根本的面向Web的综合个性,提供对常见框架如Struts2的反对,Spring可能治理这些框架,将Spring的资源注入给框架,也能在这些框架的前后插入拦截器;
- Spring MVC:提供面向Web利用的Model-View-Controller,即MVC实现。
- Spring DAO:对JDBC的形象封装,简化了数据拜访异样的解决,并能对立治理JDBC事务;
- Spring ORM:对现有的ORM框架的反对;
下图对应的是Spring 4.x的版本,5.x版本中Web模块的Portlet组件曾经被废除
2、Spring 的长处?
(1)spring属于低侵入式设计,代码的净化极低;
(2)spring的DI机制将对象之间的依赖关系交由框架解决,减低组件的耦合性;
(3)Spring提供了AOP技术,反对将一些通用工作,如平安、事务、日志、权限等进行集中式治理,从而提供更好的复用。
(4)spring对于支流的利用框架提供了集成反对。
3、Spring的IoC了解:
(1)IOC就是管制反转,指创建对象的控制权转移给Spring框架进行治理,并由Spring依据配置文件去创立实例和治理各个实例之间的依赖关系,对象与对象之间涣散耦合,也利于性能的复用。DI依赖注入,和管制反转是同一个概念的不同角度的形容,即 应用程序在运行时依赖IoC容器来动静注入对象须要的内部依赖。
(2)最直观的表白就是,以前创建对象的主动权和机会都是由本人把控的,IOC让对象的创立不必去new了,能够由spring自动生产,应用java的反射机制,依据配置文件在运行时动静的去创建对象以及治理对象,并调用对象的办法的。
(3)Spring的IOC有三种注入形式 :结构器注入、setter办法注入、依据注解注入。
4、Spring的AOP了解:
OOP面向对象,容许开发者定义纵向的关系,但并不适用于定义横向的关系,会导致大量代码的反复,而不利于各个模块的重用。
AOP,个别称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),缩小零碎中的反复代码,升高了模块间的耦合度,进步零碎的可维护性。可用于权限认证、日志、事务处理。
AOP实现的关键在于 代理模式,AOP代理次要分为动态代理和动静代理。动态代理的代表为AspectJ;动静代理则以Spring AOP为代表。
(1)AspectJ是动态代理,也称为编译时加强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ(切面)织入到Java字节码中,运行的时候就是加强之后的AOP对象。
(2)Spring AOP应用的动静代理,所谓的动静代理就是说AOP框架不会去批改字节码,而是每次运行时在内存中长期为办法生成一个AOP对象,这个AOP对象蕴含了指标对象的全副办法,并且在特定的切点做了加强解决,并回调原对象的办法。
Spring AOP中的动静代理次要有两种形式,JDK动静代理和CGLIB动静代理:
① JDK动静代理只提供接口的代理,不反对类的代理,要求被代理类实现接口。JDK动静代理的外围是InvocationHandler接口和Proxy类,在获取代理对象时,应用Proxy类来动态创建指标类的代理类(即最终真正的代理类,这个类继承自Proxy并实现了咱们定义的接口),当代理对象调用实在对象的办法时, InvocationHandler 通过invoke()办法反射来调用指标类中的代码,动静地将横切逻辑和业务编织在一起;
InvocationHandler 的 invoke(Object proxy,Method method,Object[] args):proxy是最终生成的代理对象; method 是被代理指标实例的某个具体方法; args 是被代理指标实例某个办法的具体入参, 在办法反射调用时应用。
② 如果被代理类没有实现接口,那么Spring AOP会抉择应用CGLIB来动静代理指标类。CGLIB(Code Generation Library),是一个代码生成的类库,能够在运行时动静的生成指定类的一个子类对象,并笼罩其中特定办法并增加加强代码,从而实现AOP。CGLIB是通过继承的形式做的动静代理,因而如果某个类被标记为final,那么它是无奈应用CGLIB做动静代理的。
(3)动态代理与动静代理区别在于生成AOP代理对象的机会不同,相对来说AspectJ的动态代理形式具备更好的性能,然而AspectJ须要特定的编译器进行解决,而Spring AOP则无需特定的编译器解决。
IoC让相互协作的组件放弃涣散的耦合,而AOP编程容许你把遍布于利用各层的性能分离出来造成可重用的性能组件。
5、Spring AOP外面的几个名词的概念:
(1)连接点(Join point):指程序运行过程中所执行的办法。在Spring AOP中,一个连接点总代表一个办法的执行。
(2)切面(Aspect):被抽取进去的公共模块,能够用来会横切多个对象。Aspect切面能够看成 Pointcut切点 和 Advice告诉 的联合,一个切面能够由多个切点和告诉组成。
在Spring AOP中,切面能够在类上应用 @AspectJ 注解来实现。
(3)切点(Pointcut):切点用于定义 要对哪些Join point进行拦挡。
切点分为execution形式和annotation形式。execution形式能够用门路表达式指定对哪些办法拦挡,比方指定拦挡add、search。annotation形式能够指定被哪些注解润饰的代码进行拦挡。
(4)告诉(Advice):指要在连接点(Join Point)上执行的动作,即加强的逻辑,比方权限校验和、日志记录等。告诉有各种类型,包含Around、Before、After、After returning、After throwing。
(5)指标对象(Target):蕴含连接点的对象,也称作被告诉(Advice)的对象。 因为Spring AOP是通过动静代理实现的,所以这个对象永远是一个代理对象。
(6)织入(Weaving):通过动静代理,在指标对象(Target)的办法(即连接点Join point)中执行加强逻辑(Advice)的过程。
(7)引入(Introduction):增加额定的办法或者字段到被告诉的类。Spring容许引入新的接口(以及对应的实现)到任何被代理的对象。例如,你能够应用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。
几个概念的关系图能够参考下图:
网上有张十分形象的图,形容了各个概念所处的场景和作用,贴在这里供大家了解:
6、Spring告诉(Advice)有哪些类型?
(1)前置告诉(Before Advice):在连接点(Join point)之前执行的告诉。
(2)后置告诉(After Advice):当连接点退出的时候执行的告诉(不论是失常返回还是异样退出)。
(3)盘绕告诉(Around Advice):突围一个连接点的告诉,这是最弱小的一种告诉类型。 盘绕告诉能够在办法调用前后实现自定义的行为。它也能够抉择是否继续执行连接点或间接返回它们本人的返回值或抛出异样来完结执行。
(4)返回后告诉(AfterReturning Advice):在连接点失常实现后执行的告诉(如果连接点抛出异样,则不执行)
(5)抛出异样后告诉(AfterThrowing advice):在办法抛出异样退出时执行的告诉
同一个Aspect,不同advice的执行程序:
(1)没有异常情况下的执行程序:
- around before advice
- before advice
- target method 执行
- around after advice
- after advice
- afterReturning
(2)有异常情况下的执行程序:
- around before advice
- before advice
- target method 执行
- around after advice
- after advice
- afterThrowing
- java.lang.RuntimeException: 异样产生
7、BeanFactory和ApplicationContext有什么区别?
BeanFactory和ApplicationContext是Spring的两大外围接口,都能够当做Spring的容器。
(1)BeanFactory是Spring外面最底层的接口,是IoC的外围,定义了IoC的基本功能,蕴含了各种Bean的定义、加载、实例化,依赖注入和生命周期治理。ApplicationContext接口作为BeanFactory的子类,除了提供BeanFactory所具备的性能外,还提供了更残缺的框架性能:
- 继承MessageSource,因而反对国际化。
- 资源文件拜访,如URL和文件(ResourceLoader)。
- 载入多个(有继承关系)上下文(即同时加载多个配置文件) ,使得每一个上下文都专一于一个特定的档次,比方利用的web层。
- 提供在监听器中注册bean的事件。
(2)①BeanFactroy采纳的是提早加载模式来注入Bean的,只有在应用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,咱们就不能提前发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次应用调用getBean办法才会抛出异样。
②ApplicationContext,它是在容器启动时,一次性创立了所有的Bean。这样,在容器启动时,咱们就能够发现Spring中存在的配置谬误,这样有利于查看所依赖属性是否注入。
③ApplicationContext启动后预载入所有的单实例Bean,所以在运行的时候速度比拟快,因为它们曾经创立好了。绝对于BeanFactory,ApplicationContext 惟一的有余是占用内存空间,当应用程序配置Bean较多时,程序启动较慢。
(3)BeanFactory和ApplicationContext都反对BeanPostProcessor、BeanFactoryPostProcessor的应用,但两者之间的区别是:BeanFactory须要手动注册,而ApplicationContext则是主动注册。
(4)BeanFactory通常以编程的形式被创立,ApplicationContext还能以申明的形式创立,如应用ContextLoader。
8、Spring Bean的生命周期?
简略来说,Spring Bean的生命周期只有四个阶段:实例化 Instantiation --> 属性赋值 Populate --> 初始化 Initialization --> 销毁 Destruction
但具体来说,Spring Bean的生命周期蕴含下图的流程:
(1)实例化Bean:
对于BeanFactory容器,当客户向容器申请一个尚未初始化的bean时,或初始化bean的时候须要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
对于ApplicationContext容器,当容器启动完结后,通过获取BeanDefinition对象中的信息,实例化所有的bean。
(2)设置对象属性(依赖注入):实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring依据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口实现属性设置与依赖注入。
(3)解决Aware接口:Spring会检测该对象是否实现了xxxAware接口,通过Aware类型的接口,能够让咱们拿到Spring容器的一些资源:
- ①如果这个Bean实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)办法,传入Bean的名字;
- ②如果这个Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()办法,传入ClassLoader对象的实例。
- ②如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()办法,传递的是Spring工厂本身。
- ③如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)办法,传入Spring上下文;
(4)BeanPostProcessor前置解决:如果想对Bean进行一些自定义的前置解决,那么能够让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)办法。
(5)InitializingBean:如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()办法。
(6)init-method:如果Bean在Spring配置文件中配置了 init-method 属性,则会主动调用其配置的初始化办法。
(7)BeanPostProcessor后置解决:如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)办法;因为这个办法是在Bean初始化完结时调用的,所以能够被利用于内存或缓存技术;
以上几个步骤实现后,Bean就曾经被正确创立了,之后就能够应用这个Bean了。
(8)DisposableBean:当Bean不再须要时,会通过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()办法;
(9)destroy-method:最初,如果这个Bean的Spring配置中配置了destroy-method属性,会主动调用其配置的销毁办法。
9、 Spring中bean的作用域:
(1)singleton:默认作用域,单例bean,每个容器中只有一个bean的实例。
(2)prototype:为每一个bean申请创立一个实例。
(3)request:为每一个request申请创立一个实例,在申请实现当前,bean会生效并被垃圾回收器回收。
(4)session:与request范畴相似,同一个session会话共享一个实例,不同会话应用不同的实例。
(5)global-session:全局作用域,所有会话共享一个实例。如果想要申明让所有会话共享的存储变量的话,那么这全局变量须要存储在global-session中。
10、Spring框架中的Bean是线程平安的么?如果线程不平安,那么如何解决?
Spring容器自身并没有提供Bean的线程安全策略,因而能够说Spring容器中的Bean自身不具备线程平安的个性,然而具体情况还是要联合Bean的作用域来探讨。
(1)对于prototype作用域的Bean,每次都创立一个新对象,也就是线程之间不存在Bean共享,因而不会有线程平安问题。
(2)对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因而是存在线程平安问题的。然而如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查问以外的操作,那么这个单例Bean是线程平安的。比方Controller类、Service类和Dao等,这些Bean大多是无状态的,只关注于办法自身。
有状态Bean(Stateful Bean) :就是有实例变量的对象,能够保留数据,是非线程平安的。无状态Bean(Stateless Bean):就是没有实例变量的对象,不能保留数据,是不变类,是线程平安的。
对于有状态的bean(比方Model和View),就须要自行保障线程平安,最通俗的解决办法就是将有状态的bean的作用域由“singleton”改为“prototype”。
也能够采纳ThreadLocal解决线程平安问题,为每个线程提供一个独立的变量正本,不同线程只操作本人线程的正本变量。
ThreadLocal和线程同步机制都是为了解决多线程中雷同变量的拜访抵触问题。同步机制采纳了“工夫换空间”的形式,仅提供一份变量,不同的线程在拜访前须要获取锁,没取得锁的线程则须要排队。而ThreadLocal采纳了“空间换工夫”的形式。ThreadLocal会为每一个线程提供一个独立的变量正本,从而隔离了多个线程对数据的拜访抵触。因为每一个线程都领有本人的变量正本,从而也就没有必要对该变量进行同步了。
11、Spring基于xml注入bean的几种形式:
- set()办法注入;
- 结构器注入:①通过index设置参数的地位;②通过type设置参数类型;
- 动态工厂注入;
- 实例工厂;
具体内容请参考这篇文章:Spring中bean的注入形式
12、Spring如何解决循环依赖问题:
具体内容强烈建议参考这篇文章:Spring如何解决循环依赖问题
循环依赖问题在Spring中次要有三种状况:
- (1)通过构造方法进行依赖注入时产生的循环依赖问题。
- (2)通过setter办法进行依赖注入且是在多例(原型)模式下产生的循环依赖问题。
- (3)通过setter办法进行依赖注入且是在单例模式下产生的循环依赖问题。
在Spring中,只有第(3)种形式的循环依赖问题被解决了,其余两种形式在遇到循环依赖问题时都会产生异样。这是因为:
- 第一种构造方法注入的状况下,在new对象的时候就会梗塞住了,其实也就是”先有鸡还是先有蛋“的历史难题。
- 第二种setter办法(多例)的状况下,每一次getBean()时,都会产生一个新的Bean,如此重复上来就会有无穷无尽的Bean产生了,最终就会导致OOM问题的呈现。
Spring在单例模式下的setter办法依赖注入引起的循环依赖问题,次要是通过二级缓存和三级缓存来解决的,其中三级缓存是次要功臣。解决的外围原理就是:在对象实例化之后,依赖注入之前,Spring提前裸露的Bean实例的援用在第三级缓存中进行存储。
13、Spring的主动拆卸:
在spring中,应用autowire来配置主动装载模式,对象无需本人查找或创立与其关联的其余对象,由容器负责把须要相互协作的对象援用赋予各个对象。
(1)在Spring框架xml配置中共有5种主动拆卸:
- no:默认的形式是不进行主动拆卸的,通过手工设置ref属性来进行拆卸bean。
- byName:通过bean的名称进行主动拆卸,如果一个bean的 property 与另一bean 的name 雷同,就进行主动拆卸。
- byType:通过参数的数据类型进行主动拆卸。
- constructor:利用构造函数进行拆卸,并且构造函数的参数通过byType进行拆卸。
- autodetect:主动探测,如果有构造方法,通过 construct的形式主动拆卸,否则应用 byType的形式主动拆卸。
(2)基于注解的主动拆卸形式:
应用@Autowired、@Resource注解来主动拆卸指定的bean。在应用@Autowired注解之前须要在Spring配置文件进行配置,<context:annotation-config />。在启动spring IoC时,容器主动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器主动查找须要的bean,并拆卸给该对象的属性。在应用@Autowired时,首先在容器中查问对应类型的bean:
如果查问后果刚好为一个,就将该bean拆卸给@Autowired指定的数据;
如果查问的后果不止一个,那么@Autowired会依据名称来查找;
如果上述查找的后果为空,那么会抛出异样。解决办法时,应用required=false。
@Autowired可用于:构造函数、成员变量、Setter办法注:@Autowired和@Resource之间的区别:
(1) @Autowired默认是依照类型拆卸注入的,默认状况下它要求依赖对象必须存在(能够设置它required属性为false)。
(2) @Resource默认是依照名称来拆卸注入的,只有当找不到与名称匹配的bean才会依照类型来拆卸注入。
14、Spring事务的实现形式和实现原理:
Spring事务的实质其实就是数据库对事务的反对,没有数据库的事务反对,spring是无奈提供事务性能的。Spring只提供对立事务管理接口,具体实现都是由各数据库本人实现,数据库事务的提交和回滚是通过binlog或者undo log实现的。Spring会在事务开始时,依据以后环境中设置的隔离级别,调整数据库隔离级别,由此保持一致。
(1)Spring事务的品种:
spring反对编程式事务管理和申明式事务管理两种形式:
①编程式事务管理应用TransactionTemplate。
②申明式事务管理建设在AOP之上的。其本质是通过AOP性能,对办法前后进行拦挡,将事务处理的性能编织到拦挡的办法中,也就是在指标办法开始之前启动一个事务,在执行完指标办法之后依据执行状况提交或者回滚事务。
申明式事务最大的长处就是不须要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相干的事务规定申明或通过@Transactional注解的形式,便能够将事务规定利用到业务逻辑中,缩小业务代码的净化。惟一有余中央是,最细粒度只能作用到办法级别,无奈做到像编程式事务那样能够作用到代码块级别。
(2)spring的事务流传机制:
spring事务的流传机制说的是,当多个事务同时存在的时候,spring如何解决这些事务的行为。事务流传机制实际上是应用简略的ThreadLocal实现的,所以,如果调用的办法是在新线程调用的,事务流传实际上是会生效的。
① PROPAGATION_REQUIRED:(默认流传行为)如果以后没有事务,就创立一个新事务;如果以后存在事务,就退出该事务。② PROPAGATION_REQUIRES_NEW:无论以后存不存在事务,都创立新事务进行执行。
③ PROPAGATION_SUPPORTS:如果以后存在事务,就退出该事务;如果以后不存在事务,就以非事务执行。‘
④ PROPAGATION_NOT_SUPPORTED:以非事务形式执行操作,如果以后存在事务,就把以后事务挂起。
⑤ PROPAGATION_NESTED:如果以后存在事务,则在嵌套事务内执行;如果以后没有事务,则按REQUIRED属性执行。
⑥ PROPAGATION_MANDATORY:如果以后存在事务,就退出该事务;如果以后不存在事务,就抛出异样。
⑦ PROPAGATION_NEVER:以非事务形式执行,如果以后存在事务,则抛出异样。
(3)Spring中的隔离级别:
① ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,应用数据库默认的事务隔离级别。② ISOLATION_READ_UNCOMMITTED:读未提交,容许事务在执行过程中,读取其余事务未提交的数据。
③ ISOLATION_READ_COMMITTED:读已提交,容许事务在执行过程中,读取其余事务曾经提交的数据。
④ ISOLATION_REPEATABLE_READ:可反复读,在同一个事务内,任意时刻的查问后果都是统一的。
⑤ ISOLATION_SERIALIZABLE:所有事务一一顺次执行。
15、Spring 框架中都用到了哪些设计模式?
(1)工厂模式:Spring应用工厂模式,通过BeanFactory和ApplicationContext来创建对象;
(2)单例模式:Bean默认为单例模式。
(3)代理模式:Spring的AOP性能用到了JDK的动静代理和CGLIB字节码生成技术;
(4)模板办法:用来解决代码反复的问题。比方.RestTemplate, JmsTemplate, JpaTemplate。
(5)观察者模式:Spring事件驱动模型就是观察者模式的一个经典利用。
(6)包装器设计模式:能够依据客户的需要可能动静切换不同的数据源。比方咱们的我的项目须要连贯多个数据库,客户在每次拜访中依据须要会去拜访不同的数据库。
(7)适配器模式:Spring AOP的加强或告诉(Advice)应用到了适配器模式,Spring MVC中也是用到了适配器模式适配Controller。
16、Spring框架中有哪些不同类型的事件?
Spring 提供了以下5种规范的事件:
(1)上下文更新事件(ContextRefreshedEvent):在调用ConfigurableApplicationContext 接口中的refresh()办法时被触发。
(2)上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()办法开始/从新开始容器时触发该事件。
(3)上下文进行事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()办法进行容器时触发该事件。
(4)上下文敞开事件(ContextClosedEvent):当ApplicationContext被敞开时触发该事件。容器被敞开时,其治理的所有单例Bean都被销毁。
(5)申请处理事件(RequestHandledEvent):在Web利用中,当一个http申请(request)完结触发该事件。
如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被公布当前,bean会主动被告诉。