基础知识点五

十、Spring/Spring MVC

90.为什么要使用 spring?

1、方便解耦,便于开发(Spring就是一个大工厂,可以将所有对象的创建和依赖关系维护都交给spring管理)

2、spring支持aop编程(spring提供面向切面编程,可以很方便的实现对程序进行权限拦截和运行监控等功能)

3、声明式事务的支持(通过配置就完成对事务的支持,不需要手动编程)

4、方便程序的测试,spring 对junit4支持,可以通过注解方便的测试spring 程序

5、方便集成各种优秀的框架

6、降低javaEE API的使用难度(Spring 对javaEE开发中非常难用的一些API 例如JDBC,javaMail,远程调用等,都提供了封装,是这些API应用难度大大降低)

91.解释一下什么是 aop?

AOP为Aspect Oriented Programming,意为面向切面编程,通过预编译方式和运行期动态代理实现,不修改源代码的情况下给程序动态统一添加功能的一种技术。利用AOP可以对业务逻辑各个部分进行隔离,从而降低耦合度,提高程序的可重用性,提高开发效率,如声明式事务管理、权限校验、日志功能等

92.解释一下什么是 ioc?

IOC(Inversion of Control)控制反转(也可以理解为依赖注入),指将对象的创建权,反转到spring容器,依赖容器注入对象,

93.spring 有哪些主要模块?

有七大模块,分别是spring Core,AOP,ORM,DAO,MVC,WEB,Context

1、spring Core模块是spring的核心类库,所有功能都依赖该类库,主要实现IOC功能。

2、AOP模块,提供AOP机制,有常用的拦截器供用户自定义和配置

3、ORM模块提供对常用的ORM框架的管理和辅助支持,常用的有Hibernate、mybatis、JDAO等框架,该模块不对ORM进行实现,仅对ORM进行封装并管理。

4、DAO模块,对JDBC进行封装,并统一管理JDBC事务,不对JDBC进行实现

5、WEB模块,提供对常见的框架的支持如:Structs2、JSF、SpringMVC等,管理这些框架并将资源注入给框架。

6、Context模块,提供框架式的Bean访问方式,其他程序可通过Context访问spring的Bean资源

7、MVC模块,spring提供一套轻量级的MVC实现

94.spring 常用的注入方式有哪些?

主要三种:构造方法注入、setter注入、基于注解注入

95.spring 中的 bean 是线程安全的吗?

缺省的情况下是单例模式,线程不安全;可以通过设置scope,prototype:bean每次注入都会创建新的对象;request:单个请求都会复用同一个对象;session:同一个会话复用一个对象;application:servletContext生命周期复用一个单例对象。;websocket:在websocket的生命周期中复用一个单例对象。

96.spring 支持几种 bean 的作用域?

看上面题目的答案。

97.spring 自动装配 bean 有哪些方式?

no:不进行自动装配,手动设置Bean的依赖关系

byName:根据Bean的名字@Resource

byType:根据Bean的类型@Autowired

constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则导致错误

autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用按类型自动装配(spring3.0以后被弃用)

98.spring 事务实现方式有哪些?

1、编程式事务管理,beginTransaction()、commit()、rollback()等事务管理相关的方法

2、基于TransactionProxyFactoryBean的声明式事务管理

3、基于 @Transactional 的声明式事务管理

4、基于Aspectj AOP配置事务

99.补充一个问题:spring的事务传播机制?

事务传播性,一般是在事务嵌套时使用,比如在事务A里面调用了另外一个使用事务的方法,那么这两个事务是各自作为独立事务执行提交,还是内层事务合并到外层事务一起提交,这就是事务传播性要确定的问题。常用的传播性:1、propagation_required,spring默认事务传播机制,如果外层有事务则当前事务加入到外层事务,一块提交一块回滚,如果外层没有事务则当前开启一个新事务;2、propagation_requires_new,每次新开启一个事务,同时把外层事务挂起,当前新事务执行完毕后才恢复上层事务执行;3、propagation_supports,该传播机制如果外层有事务则加入该事务,如果不存在也不会创建新事务,直接使用非事务方式执行;4、propagation_not_supported,该传播机制不支持事务,如果外层存在事务则挂起外层事务 ,然后执行当前逻辑,执行完毕后,恢复外层事务;5、propagation_never,该传播机制不支持事务,如果外层存在事务则直接抛出异常;6、propagation_mandatory,该传播机制是说配置了该传播性的方法只能在已经存在事务的方法中被调用,如果在不存在事务的方法中被调用,会抛出异常;7、propagation_nested,该传播机制特点是可以保存状态保存点,当事务回滚后会回滚到某一个保存点上,从而避免所有嵌套事务都回滚

99.说一下 spring 的事务隔离?

事务隔离性指多个事务并发执行的时候相互之间不受彼此的干扰,隔离级别:1、Read Uncommitted,读未提交隔离级别,指一个事务中可以读取其他事务未提交的数据,会导致脏读;2、Read Committed,读已提交隔离级别,指一个事务只能读取到其他事务已经提交的数据,可能导致同一个事务中多次搜查结果不一样,会导致不可重复读和幻读,避免脏读(oracle默认是该隔离级别);3、Repeatable Read,可重复读隔离级别,一个事务内多次查询数据时候查询的数据内容和第一次查询的一致,避免脏读/不可重复读;4、Serializable,串行化隔离级别,就是多个事务串行化一个个按照顺序执行,不存在并发问题,事务二会等到事务一提交或超时才能提交事务

100.说一下 spring mvc 运行流程?

1、用户发送请求至DispatcherServlet;2、dispatchServlet收到请求调用处理映射器HandlerMapping;3、处理映射器根据请求url找到具体处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet;4、DispatcherServlet根据处理器Handler获得处理器适配器HandlerAdapter执行HandlerAdapter处理一系列操作,如:参数封装、数据格式转换、数据验证等;5、执行处理器Handler(Controller,也叫页面控制器);6、Handler执行完成返回ModelAndView;7、HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet;8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器;9、ViewReslover解析后返回具体View;10、DispatcherServlet对View进行渲染视图(即是将模型数据model填充至视图中);11、DispatcherServlet响应用户

101.spring mvc 有哪些组件?

1、前端控制器(DispatcherServlet),作用负责用户请求接收;2、解析器(ViewReslover),负责视图解析view;3、适配器(HandlerAdapter),负责执行Handler;4、映射器(HandlerMapping),负责根据url查找Handler

102.@RequestMapping 的作用是什么?

用来处理请求地址映射的注解,可用于类或方法上;用于类上,表示类中所有响应请求的方法都是以该地址作为父路径

103.@Autowired 的作用是什么?

根据Bean的类型自动注入对象

十一、Spring Boot/Spring Cloud

104.什么是 spring boot?

spring boot 是用来简化spring应用的初始搭建以及开发过程,整合了spring,SpringMVC等框架,默认了很多配置,少量代码就能创建一个独立、产品级别spring应用。springBoot为spring平台及第三方库提供开箱即用的设置

105.为什么要用 spring boot?

1、简化使用spring过程;2、项目快速搭建,无需配置的自动整合第三方框架;3、可以完全不使用XML配置文件,只需自动配置和Java Config;4、内嵌Servlet容器,降低对环境的要求,可以使用命令直接执行项目5、运行中应用状态的监控;6、对主流开发框架无配置集成;7、与云计算的天然继承

106.spring boot 核心配置文件是什么?

application.properties

107.spring boot 配置文件有哪几种类型?它们有什么区别?

配置文件有两种类型:application.properties和application.yml;

properties文件是键值对形式(如:com.user.name:wbj);

yml文件是梯级呈现,进行赋值时必须在“:”后面缩进一个空格键

(如:com:

    user: wbj

    age: 18)

108.spring boot 有哪些方式可以实现热部署?

 1、使用spring Loaded;2、使用spring-boot-devtools(pom.xml中添加依赖,正常启动即可)

109.jpa 和 hibernate 有什么区别?

jpa全称:Java Persistence API(java持久化API),jpa是持久化接口规范,jpa是Hibernate是遵循的规范之一的一种实现

110.什么是 spring cloud?spring cloud是微服务工具包(提供全套分布式系统解决方案),为开发者提供了在分布式系统的配置管理、服务发现、断路器、智能路由、微代理、控制总线等开发工具包

111.spring cloud 断路器的作用是什么?防止分布式系统中出现这种瀑布似的连锁反应导致灾难

112.spring cloud 的核心组件有哪些?1、服务发现(Netflix Eureka)2、客户端负载均衡(Netflix Ribbon)3、断路器(Netflix Hystrix)4、服务网关(Netflix Zuul)5、分布式配置(Spring Cloud Config)

十二、Hibernate

113.为什么要使用 hibernate?

1、对JDBC访问数据库代码做了封装,大大简化了数据访问层繁琐的重复性代码;

2、是一个基于JDBC的主流持久化框架,是个优秀的ORM实现。很大程度简化DAO层编码工作

3、使用java反射机制,而不是字节码增强程序来实现透明性;

4、性能好,轻量级框架,映射灵活,支持各种关系数据库,从一对一到多对多各种复杂关系

114.什么是 ORM 框架?

ORM(Object Relational Mapping)对象关系映射,通过类与数据库表的映射关系,将对象持久化到数据库中。

115.hibernate 中如何在控制台查看打印的 sql 语句?

在spring的配置文件增加:<prop key="hibernate.show_sql">true</prop> ,或者在hibernate配置文件中增加<property name="show_sql">true</property>

116.hibernate 有几种查询方式?三种:HQL、QBC(命名查询)、原生SQL查询

117.hibernate 实体类可以被定义为 final 吗?

可以,但是这样做法不好,因为hibernate使用代理模式在延迟关联情况下提高性能,如果定义为final类之后,因为java不允许对final类进行扩展,所以hibernate就无法再使用代理,如此就限制了提升性能。不过,如果你的持久化类实现了一个接口并且在该接口中声明了所有定义于实体类中所有public的方法的话,就能避免出现前面的不利后果

118.在 hibernate 中使用 Integer 和 int 做映射有什么区别?

integer是对象,可以为null,int是普通类型,不可为null,所以映射的字段可以为空时只能使用Integer

119.hibernate 是如何工作的?1、创建Configeration类的实例,将配置信息(config.xml)读入到内存,一个Configeration实例代表hibernate所有java类到sql数据库映射的集合;2、创建sessionFactory实例,把Configeration对象中所有配置信息拷贝到sessionFactory缓存中,sessionFactory实例创建后不再与Configeration对象关联,sessionFactory缓存中有hibernate配置信息和OR映射元数据。3、调用sessionFactory创建session方法( Session s=sessionFactory.openSession(););4、通过session接口提供各种方法操作数据库

120.get()和 load()的区别?

1、load()是延迟加载,仅仅得到一个保存id的代理对象,真正查询其他属性时才会从数据库中查询,查询不到数据则会报ObjectNotFoundException异常;2、get()是直接到数据库查询,查询不到会报NullPointException异常

121.说一下 hibernate 的缓存机制?

hibernate缓存包括两大类:一级缓存和二级缓存。一级缓存又称“session的缓存”,由于session对象生命周期对应一个数据库事务或者一个应用事务,因此一级缓存是事务级的缓存;二级缓存又称“sessionFactory的缓存”,由于sessionFactory对象生命周期和应用程序整个过程对应,因此二级缓存是进程范围或者集群范围缓存,所以有可能出现并发问题(采取事务隔离级别策略),默认情况下,sessionFactory不会启用这个插件。hibernate管理缓存实例无论何时,当你给save(),update()或saveOrUpdate()方法传递一个对象时,或使用load()、get()、list()、iterate()或scroll()方法获得一个对象时,该对象都将被加入到session内部缓存中。当随后flush()方法调用时,对象将会同步到数据库。如果不希望此同步操作发生,可以调用evict()方法,从一级缓存中去掉这些对象及集合

122.hibernate 对象有哪些状态?

三种状态:瞬时态(没有id,不与session关联);持久态(有id,与session关联);托管态(有id,不与session关联)

123.在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?

getCurrentSession保存对象事务自动提交且无需手动关闭,openSession需要手动提交事务且关闭

124.hibernate 实体类必须要有无参构造函数吗?为什么?

实体类对象的创建是hibernate动态通过反射技术生成,需要无参构造方法。

如果没有提供任何构造方法,虚拟机会自动提供默认无参构造方法,如果提供有参的构造方法的话,虚拟机不再为你提供无参默认构造方法,这时必须手动提供无参构造方法;

十三、Mybatis

125.mybatis 中 #{}和 ${}的区别是什么?#{}是参数占位符?,即sql预编译;$()是字符串替换,即sql拼接

126.mybatis 有几种分页方式?1、数组分页,获取所有数据,通过list接收后进行分页操作;2、借助sql语句进行分页,配置xml的sql语句为:“select * from Blog limit #{currIndex},#{pageSize}“,通过map传参,Map param = new LinkedHashMap();param.put("currIndex",4);param.put("pageSize",4),调用session.selectList(“id”,param);3、RowBounds分页,RowBounds rowBounds = new RowBounds(0, 4);List<Blog> list = session.selectList(statement,null,rowBounds);4、拦截器分页;5、插件pageHelper分页(起到物理分页作用),PageHelper.startPage(1,4);

127.RowBounds 是一次性查询全部结果吗?为什么?

表面是在“所有”数据中检索数据,其实并非一次性查询,因为mybatis对jdbc是封装的,有个FetchSize配置,规定每次最多从数据库中查询多少条数据,可以有效的防止内存溢出

128.mybatis 逻辑分页和物理分页的区别是什么?

逻辑分页利用游标分页,好处是所有数据库都统一,坏处是效率低;

物理分页就是数据库本身提供了分页方式,如mysql的limit,好处是效率高,坏处就是不同数据库不同搞法。hibernate采用的是物理分页,mybatis默认采用逻辑分页。

129.mybatis 是否支持延迟加载?延迟加载的原理是什么?

延迟加载:先从单表查询、需要时再从关联表去关联查询;原理:使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询出来,然后调用a.setB(),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。

一对多的mapper配置:

<resultMap type="com.cn.entity.Course" id="course">
<id column="id" property="id"/>
<result column="name" property="name"/>
<association property="user" javaType="com.cn.entity.User" select="findUserById" column="user_id"/>
</resultMap>

<select id="findUserById" resultType="com.cn.entity.User">
select * from user where id = #{id}
</select>
<select id="course" resultMap="course">
select * from course
</select>
View Code

user实体类:

private int id;
private String name;
private int age;
View Code

course实体类:

private int id;
private int user_id;
private String name;
private User user;
View Code

config的配置:

<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>

<!-- 当设置为‘true'的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。 -->
<setting name="aggressiveLazyLoading" value="true"/>
</settings>
View Code

130.说一下 mybatis 的一级缓存和二级缓存?

一级缓存指的是一个sqlSession级别的缓存,关闭session缓存也就失效;二级缓存是mapper级别缓存,作用域是mapper的同一个namespace。不同的sqlSession两次执行相同的namespace下的sql语句,且向sql中传递的参数也相同,即最终执行相同的sql语句,则第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询会从缓存中获取数据,不再去底层数据库查询,从而提高效率。

131.mybatis 和 hibernate 的区别有哪些?

hibernate封装了sql语句,具体使用与数据库无关,mybatis的sql语句需要根据所用数据库手动写;hibernate每一个关联关系都可以详细地设置是否延迟加载,而mybatis的延迟加载是全局配置的

132.mybatis 有哪些执行器(Executor)?

1、simpleExecutor:每执行一次update或select,就开启一个statement对象,用完立刻关闭;2、ReuseExecutor:执行update或select,以sql作为key查找statement对象,存在就使用,不存在就创建,用完后,不关闭statement对象,而是放置于Map内,供下次使用,简言之,就是重复使用statement对象;3、BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个statement对象,每个statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。设置执行器方式:1、全局配置文件中配置,<setting name="defaultExecutorType" value="BATCH"/>;2、获取sqlSession时获取,如:sqlSessionFactory.openSession(ExecutorType.SIMPLE);

133.mybatis 分页插件的实现原理是什么?

原理是我们执行sql语句之前动态的将sql语句拼接了分页语句

134.mybatis 如何编写一个自定义插件?

自定义插件可以拦截的分别有:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

案例:实现Interceptor接口,

package com.cn.plugin;
import java.util.Properties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

@Intercepts(value = {@Signature(
        type = Executor.class, 
        method = "query", 
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class testPlugin implements Interceptor{
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("我的插件");
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) {
    }
}
View Code

配置文件中注册插件:

<plugins>
  <plugin interceptor="com.cn.plugin.testPlugin"></plugin>
</plugins>
View Code

 

posted @ 2019-04-09 19:10  亦真亦假,何必当真  阅读(203)  评论(0编辑  收藏  举报