本文由公众号【码说TM】收录
Spring
SpringMVC
Mybatis
1. Spring的概念
轻量级的IOC和AOP容器框架,能够为Java应用程序提供基础性服务,目的是简化企业应用程序的开发,让开发者专注于业务需求。有三种常见的配置方式,分别是基于XML、注解、Java的配置。
Spring拥有七大主要模块:
Spring Core:核心库,Spring所有功能都依赖于该库。Core主要实现IOC功能,Spring所有的功能都是通过IOC实现的。
AOP:AOP=Aspect Oriented Programming,是OOP的延续,提供拦截器机制,用户能够自定义和配置拦截器。应用场景:日志记录、性能统计、安全控制、事务处理、异常处理等等。
ORM:该模块提供对ORM框架的管理和辅助支持。Spring本身并不对ORM进行实现,仅对常用的ORM框架(Hibernate、ibatis)进行封装和管理。
DAO:Spring 提供对JDBC的支持,对JDBC进行封装,允许JDBC使用Spring资源,并能统一管理JDBC事物,并不对JDBC进行实现。
WEB模块:管理常见的WEB框架(Struts1,WEBWORK,JSF),将Spring的资源注入给框架,也可以在框架前后插入拦截器。
Context模块:提供框架式的Bean访问方式,其他程序可以通过Context访问Spring的Bean资源,相当于资源注入。
MVC模块:该模块为Spring提供了一套轻量级的MVC实现,相对于Struts,Spring自己的MVC框架更加简洁和方便。
2. Spring的优点
(1)低侵入式设计,代码的污染极低;
(2)spring的DI机制将对象之间的依赖关系交由框架处理,减低组件的耦合性;
(3)提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用。
(4)spring对于主流的应用框架提供了集成支持。
3. BeanFactory和ApplicationContext有什么区别
BeanFactory和ApplicationContext是Spring的两大核心接口,它们都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。
ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:
(1)继承MessageSource,因此支持国际化。
(2)统一的资源文件访问方式。
(3)提供在监听器中注册bean的事件。
(4)同时加载多个配置文件。
(5)载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;但是ApplicationContext在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。
ApplicationContext 比BeanFactory占用更多的内存空间。当应用程序配置Bean较多时,程序启动较慢。
BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。
BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。
4. 简述Spring Bean的生命周期
(1)实例化Bean:当有客户端请求一个未被初始化的bean时或者初始化bean的时候需要注入另一个尚未初始化的依赖时,BeanFactory会调用createBean进行初始化。ApplicationContext容器会在当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的bean。
(2)依赖注入:实例化之后的对象会被封装在BeanWrapper中,然后Spring会根据BeanDefinition中的信息和BeanWrapper提供的设置属性的接口完成依赖注入。
(3)处理Aware接口:Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:
①如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的就是Spring配置文件中Bean的id值;
②如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。
③如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;
(4)BeanPostProcessor:该接口能够通过postProcessBeforeInitialization(Object obj, String s)方法让用户能够自定义处理Bean。由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;
(5)InitializingBean 与 init-method:如果Bean在Spring配置文件中配置了init-method属性,就会自动调用预先配置的初始化方法。至此,Bean完成了创建的所有步骤,之后就可以使用这个Bean了。
(6)DisposableBean:当Bean不再需要时,就会清洗这个Bean,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;
(7)destroy-method:如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
5. 简述Spring中bean的作用域
Spring容器中的bean可以分为5个范围:
(1)singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
(2)prototype:为每一个bean请求提供一个实例。
(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
(5)global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。
6. Spring框架中的单例Beans是线程安全的吗
Spring框架并没有对单例bean进行任何多线程的封装处理。大部分的Spring bean并没有可变的状态(比如Serview类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多种状态的话,就需要自行保证线程安全。最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“prototype”。
7. Spring如何处理线程并发问题
在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域,因为Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,解决线程安全问题。
ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。
ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
8. Spring基于xml注入bean的几种方式
(1)Set方法注入;
(2)构造器注入:①通过index设置参数的位置;②通过type设置参数类型;
(3)静态工厂注入;
(4)实例工厂;
9. Spring的自动装配
在spring中,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象,使用autowire来配置自动装载模式。
在Spring框架xml配置中共有5种自动装配:
(1)no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。
(2)byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。
(3)byType:通过参数的数据类型进行自动装配。
(4)constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
(5)autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
10. Spring框架中用到了哪些设计模式
(1)工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
(2)单例模式:Bean默认为单例模式。
(3)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
(4)模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
(5)观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现--ApplicationListener。
11. Spring 事务的实现方式和实现原理
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
(1)Spring事务的种类:
Spring支持编程式事务管理和声明式事务管理两种方式:
①编程式事务管理使用TransactionTemplate。
②声明式事务管理建立在AOP之上的。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
(2)Spring的事务传播行为:
Spring事务的传播行为说的是,当多个事务同时存在的时候,Spring如何处理这些事务的行为。
① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
(3)Spring中的隔离级别:
① ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
② ISOLATION_READ_UNCOMMITTED:读未提交,允许另外一个事务可以看到这个事务未提交的数据。
③ ISOLATION_READ_COMMITTED:读已提交,保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新。
④ ISOLATION_REPEATABLE_READ:可重复读,保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新。
⑤ ISOLATION_SERIALIZABLE:一个事务在执行的过程中完全看不到其他事务对数据库所做的更新。
12. Spring在SSM中起什么作用
作用:Bean工厂,用来管理Bean的生命周期和框架集成。
两大核心:(1)IOC/DI(控制反转/依赖注入),Spring顶层容器为BeanFactory(2)AOP(面向切面编程)
13. IOC在项目中的作用
IOC解决对象之间的依赖问题,把所有Bean的依赖关系通过配置文件或注解关联起来,降低耦合度。
14. Spring常用注解
注册:@Controller @Service @Component
注入:@Autowired @Resource
请求地址:@RequestMapping
返回具体数据类型而非跳转:@ResponseBody
15. Spring DI的三种方式
(1) 构造器注入:通过构造方法初始化
(2) setter方法注入:通过setter方法初始化
(3) 接口注入
1. SpringMvc 的控制器是不是单例模式,如果是,有什么问题,怎么解决?
是单例模式,在多线程访问时会有线程安全问题。解决这种问题,不能够使用同步,并且不能再控制器中写字段。
2. SpringMVC控制器注解
@Controller:该注解表明被注解类扮演控制器的角色。
3. @RequestMapping 注解用在类上的作用?
用来映射一个URL到一个类或者一个特定的处理方法上
4. 前台多个参数,这些参数都是一个对象,快速得到对象?
直接在方法中声明这个对象,SpringMVC就自动把属性赋值到这个对象里面
5. SpringMVC中如何转发和重定向
(1)转发:在返回值前面加"forward:"
(2)重定向:在返回值前面加"redirect:"
6. SpringMVC和Ajax之间如何相互调用
通过JackSon框架把java里面对象直接转换成js可识别的json对象,具体步骤如下:
(1) 加入JackSon.jar
(2) 在配置文件中配置json的映射
(3) 在接受Ajax方法里面直接返回Object,list等,方法前面需要加上注解@ResponseBody
7. SpringMvc的工作流程
(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
8. Struts2和SpringMVC的区别有哪些
Struts2 | SpringMVC | |
---|---|---|
入口 | Filter过滤器 | 一个Servlet(前端控制器) |
开发方式 | 基于类开发,通过类的属性传递参数,只能设置为多例 | 基于方法开发(一个url对应一个方法),请求参数传递到方法形参,可以为单例也可以为多例(建议单例) |
请求方式 | 值栈存储请求和响应的数据,通过OGNL存取数据 | 通过参数解析器将request请求内容解析,给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面,jsp视图解析器默认使用的是jstl。 |
9. 如何配置拦截器拦截get方法
在@RequestMapping注解里面加上method=RequestMethod.GET。
10. 怎样在方法里面得到Request或Session
直接在方法的形参中声明request,SpringMvc就自动把request对象传入。
11. SpringMVC使用什么对象从后台向前台传递数据
通过ModelMap对象,可以在这个对象里面调用put方法向其中添加对象,前台可以通过el表达式拿到。
12. 注解的原理是什么
注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。通过反射获取注解时,返回的是Java运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。
1.Mybatis优缺点
优点:
(1)基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
(2)与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
(3)很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
(4)能够与Spring很好的集成;
(5)提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
缺点:
(1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
2. Mybatis框架适用场合
对性能的要求很高,或者需求变化较多的项目
3. MyBatis与Hibernate有哪些不同
(1)Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。
(2)Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。
(3)Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用hibernate开发可以节省很多代码,提高效率。
4. #{}和${}的区别是什么?
#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
5. 当实体类中的属性名和表中的字段名不一样时应当如何处理
两种解决方案:
(1)通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
(2)通过
6. Mybatis如何进行分页
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页
7. 分页插件的原理是什么
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
8. Mybatis是如何将sql执行结果封装为目标对象并返回的,都有哪些映射形式
第一种是使用
第二种是使用sql列的别名功能,将列的别名书写为对象属性名。
有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
9. Mybatis动态sql有什么用,执行原理是什么,总共有哪些动态sql
Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值 完成逻辑判断并动态拼接sql的功能。
Mybatis提供了9种动态sql标签:trim 、where 、set 、foreach 、if choose 、when 、otherwise 、bind。
10. Mybatis是否支持延迟加载
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
11. Mybatis的一级、二级缓存
(1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
(2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置
(3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新。
12. 什么是MyBatis的接口绑定?有哪些实现方式
接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多。
13.使用MyBatis的mapper接口调用时有哪些要求
(1)Mapper接口方法名和mapper.xml中定义的每个sql的id相同;
(2)Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;
(3)Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;
(4)Mapper.xml文件中的namespace即是mapper接口的类路径。