Spring
1、什么是spring框架?
spring 的特点:
轻量:从大小和开销方面而言spring都是轻量的,处理开销也是微不足道的。
IOC:削减计算机之间的耦合,降低程序代码中的依赖关系。
AOP:通过配置管理特性spring的AOP,可以将一些通用的任务,如安全,事务,日志等集中进行管理,提高了程序的复用性和管理型。
容器:Spring提供了容器功能,容器可以管理对象的生命周期、对象与对象间的关系、我们可以通过编写XML来设置对象关系和初始值,这样容器在启动之后,所有的对象都直接可以使用,不用编写任何编码来产生对象。Spring有两种不同的容器:Bean工厂以及应用上下文。
框架:可以将简单的组件配置,组成复杂的应用,spring也提供了很多基础功能(事务管理,持久化框架集成)将应用逻辑留给开发者。
2、spring的作用?
3、Spring有哪些应用场景
应用场景:JavaEE企业应用开发,包括SSH、SSM等
Spring价值:
- Spring是非侵入式的框架,目标是使应用程序代码对框架依赖最小化;
- Spring提供一个一致的编程模型,使应用直接使用POJO开发,与运行环境隔离开来;
- Spring推动应用设计风格向面向对象和面向接口开发转变,提高了代码的重用性和可测试性;
4、Spring 框架中都用到了哪些设计模式?
- 工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
- 单例模式:Bean默认为单例模式。
- 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
- 模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
- 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
5、Spring 应用程序有哪些不同组件?
Spring 应用一般有以下组件:
- 接口 - 定义功能。
- Bean 类 - 它包含属性,setter 和 getter 方法,函数等。
- Bean 配置文件 - 包含类的信息以及如何配置它们。
- Spring 面向切面编程(AOP) - 提供面向切面编程的功能。
- 用户程序 - 它使用接口。
谈谈自己对于Spring IOC和AOP的理解
IOC
IOC(Inversion Of Controll,控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由给Spring框架来管理。IOC在其他语言中也有应用,并非Spring特有。IOC容器是Spring用来实现IOC的载体,IOC容器实际上就是一个Map(key, value),Map中存放的是各种对象。
将对象之间的相互依赖关系交给IOC容器来管理,并由IOC容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IOC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。在实际项目中一个Service类可能由几百甚至上千个类作为它的底层,假如我们需要实例化这个Service,可能要每次都搞清楚这个Service所有底层类的构造函数,这可能会把人逼疯。如果利用IOC的话,你只需要配置好,然后在需要的地方引用就行了,大大增加了项目的可维护性且降低了开发难度。
Spring时代我们一般通过XML文件来配置Bean,后来开发人员觉得用XML文件来配置不太好,于是Sprng Boot注解配置就慢慢开始流行起来。
AOP
AOP(Aspect-Oriented Programming,面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。
Spring AOP是基于动态代理的,如果要代理的对象实现了某个接口,那么Spring AOP就会使用JDK动态代理去创建代理对象;而对于没有实现接口的对象,就无法使用JDK动态代理,转而使用CGlib动态代理生成一个被代理对象的子类来作为代理。
当然也可以使用AspectJ,Spring AOP中已经集成了AspectJ,AspectJ应该算得上是Java生态系统中最完整的AOP框架了。使用AOP之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,这样可以大大简化代码量。我们需要增加新功能也方便,提高了系统的扩展性。日志功能、事务管理和权限管理等场景都用到了AOP。
Spring控制反转(IOC)
1、什么是Spring IOC 容器?
控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
2、IOC 有什么作用?
- 管理对象的创建和依赖关系的维护。
- 解耦降低了依赖,由容器去维护具体的对象的创建。
- bean对象生命周期管理。
3、使用IOC容器的优点?
- IOC和DI的配合使用能把应用的实际代码量降到最低。
- spring集成了自己的测试模块,无需依赖于junit。
- IOC容器支持立即加载和延迟加载(懒加载)。
4、spring IOC支持哪些功能
- 依赖注入
- 依赖检查
- 自动装配
- 支持集合
- 指定初始化方法和销毁方法
- 支持回调某些方法(但是需要实现 Spring 接口,略有侵入)
其中,最重要的就是依赖注入,从 XML 的配置上说,即 ref 标签。对应 Spring RuntimeBeanReference 对象。
对于 IoC 来说,最重要的就是容器。容器管理着 Bean 的生命周期,控制着 Bean 的依赖注入。
5、什么是DI?
6、什么是Spring的依赖注入?
控制反转IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:依赖注入和依赖查找
依赖注入:相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入(Dependency Injection),即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。
7、依赖注入有什么优势?
依赖注入之所以流行,是因为它是一种很可取的方式:让r容器全权负责依赖的查询,需要注入的bean对象只需要暴露出JavaBean的setter方法或者带参数的构造函数,使得容器在初始化时组装对象依赖关系。与其依赖查找方式相比,主要的优势有:
- 查找定位操作与应用代码无关
- 不依赖于容器的API,可以很容易地在任何容器以外使用应用对象。
- 不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。
8、依赖注入的三种实现方式?
构造器注入,Setter方法注入,接口注入(由于接口注入的灵活性太差,于是与spring4被废弃)
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
9、构造器依赖注入和Setter方法注入的区别
构造器依赖注入 | Setter方法注入 |
---|---|
没有部分注入 | 有部分注入(提供setter) |
不会覆盖setter属性 | 会覆盖setter属性 |
任意修改都会创建新的实例 | 任意修改都不会创建新的实例 |
适用于设置很多属性 | 适用于设置少量属性 |
两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。
Spring Beans
1、什么是Spring bean?
spring Bean是收到spring管理的bean对象,具体来说是被spring容器初始化,配置和管理的对象。spring Bean是再spring配置文件中定义的,现在也可以通过注解来定义,在spring容器初始化,注入到spring应用程序中。
2、Spring基于xml注入bean的几种方式
- setter方法注入
- 构造函数注入 ,配置index 参数位置和type参数类型
- 静态工厂注入
- 实例工厂
3、你怎样定义类的作用域?
当定义一个 在Spring里,我们还能给这个bean声明一个作用域。它可以通过bean 定义中的scope属性来定义。如,当Spring要在需要的时候每次生产一个新的bean实例,bean的scope属性被指定为prototype。另一方面,一个bean每次使用的时候必须返回同一个实例,这个bean的scope 属性 必须设为 singleton。
4、解释Spring支持的几种bean的作用域?
- singleton : bean在每个Spring ioc 容器中只有一个实例。
- prototype:一个bean的定义可以有多个实例。
- request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效
- session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
- global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的SpringApplicationContext情形下有效。缺省的Spring bean 的作用域是Singleton
注意: 缺省的Spring bean 的作用域是Singleton。使用 prototype 作用域需要慎重的思考,因为频繁创建和销毁 bean 会带来很大的性能开销。
5、Spring框架中的单例bean是线程安全的吗?
不是,Spring框架中的单例bean不是线程安全的。
spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。
实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean()了,所以就可以保证线程安全了。
- 有状态就是有数据存储功能。
- 无状态就是不会保存数据。
Spring数据访问
1、Spring支持的事务管理类型?
2、你更倾向用那种事务管理类型?
Spring面向切面编程(AOP)
1、解释AOP
2、Spring AOP and AspectJ AOP 有什么区别?AOP 有哪些实现方式?
AOP的实现关键技术在于代理模式,代理模式又分为静态代理和动态代理。
AspectJ AOP 使用的是静态代理,Spring AOP使用的是动态代理。
- AspectJ是静态代理的增强,所谓静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也成为编译期增强,它会在编译期将Aspect(切面)织入到Java字节码中,运行时候就是增强后的AOP对象
- Spring AOP使用的就是动态代理,所谓动态代理就是AOP框架不会去修改字节码文件,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含目标对象的全部方法,并且在特定切点处做了增强处理,并回调原对象的方法。
3、JDK动态代理和CGLIB动态代理的区别
Java动态代理是利用反射机制生成一个实现代理接口的匿名类,在具体方法前调用InvokeHandler来处理。而CGLIB动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
2. 如果目标对象使用了,可以强制使用CGLIB实现AOP
3. 如果目标对象没有实现接口,则必须使用CGLIB,spring会自动在CGLIB和JDK动态代理之间切换
4、解释一下Spring AOP里面的几个名词
- 切面(Aspect):切面是通知和切点的结合,通知和切点共同定义了切面的全部内容,在spring AOP中在类上加上@AspectJ来实现。
- Joinpoint(连接点):连接点代表这一个个的方法,切面代码可以通过这些点插入到应用程序的正常流程中,并添加新的行为。
- Pointcut(切入点):也是代表方法,但是这些方法并没有被增强。
- Advice(通知/增强):spring AOP拦截到Joinpoint(连接点)所要做增强过程就是通知。
- 引入(Introduction):不修改代码的前提下,运行期我们新的类中添加新的属性或方法
- 织入(Weaving):是指把增强应用到目标对象来创建新的代理对象的过程。spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。简单的说加入事务控制的过程叫做织入。
- Proxy(代理):一个类被AOP织入增强后,就产生结果代理类,其实就是代理对象。
- Target(目标对象):代理目标对象,就是被代理对象。
- 编译期:切面在目标类编译时被织入。AspectJ的织入编译器是以这种方式织入切面的。
- 类加载期:切面在目标类加载到JVM时被织入。需要特殊的类加载器,它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入就支持以这种方式织入切面。
- 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。SpringAOP就是以这种方式织入切面。
5、什么是通知?有哪五种类型的通知?
- 前置通知(Before):在目标方法被调用之前调用通知功能;
- 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
- 返回通知(After-returning ):在目标方法成功执行之后调用通知;
- 异常通知(After-throwing):在目标方法抛出异常后调用通知;
- 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。