Spring部分面试知识

对Spring的理解

spring是一个轻量级的开源框架,贯穿持久层、业务逻辑层、控制层。让每一个功能模块都可以独立的分开,降低耦合度,提高代码复用度。spring通过控制反转降低耦合性,一个对象的依赖通过被动的注入而非主动的new。spring还包括面向切面、MVC整合等等。以上是我对spring的浅显认识。

Spring IOC的理解

控制反转,指由Spring来控制对象的生命周期和对象间的关系。以前对象的创建时机是由自己把握的,开发人员主动创建对象,现在由IOC容器创建,然后注入。所有的类都会在IOC容器中注册,告诉spring你是什么,你需要什么,spring容器在合适的时机将你所需要的东西给你,控制对象生命周期的不再是引用它的对象而是spring容器。

spring先加载xml文件,Bean先在spring容器中注册,然后会进行初始化Bean,再将Bean存到容器的缓存区(Map),谁需要就给它注入,而且缓存区的对象还在,一直在,这属于单例,直到关闭spring。(scope见下面)

DI:依赖注入,动态的向某个对象注入它所需要的对象。

SpringAOP(拦截器的实现原理)

http://www.cnblogs.com/xiaolovewei/p/7919763.html

Spring事务

http://www.cnblogs.com/xiaolovewei/p/9418874.html

Spring 中的scope  ,也就是Bean的作用域

scope有Singleton、Prototype、request、session、global session。其中主要的是singleton和prototype。

singleton指的是IOC容器中只存在一个实例,所有对该对象的引用都要共享该实例。该对象自从第一次被创建以后,直到容器退出才会被销毁。就像上面说的,容器中有一个缓存区(MAP)保管这个单例。

prototype:IOC容器接收到对该对象的请求时,就会新建一个对象实例给对方。返回给对方以后,IOC容器就不在持有该对象的引用,也就是IOC只负责创建该对象实例,置于销毁,就不管了

request:XmlWebApplicationContext会为每个HTTP请求创建一个对象,当请求结束,该对象也就被销毁。

session:会为每个session创建一个对象,存活时间为session

Spring常见创建对象的注解?

@Component@Controller@ Service@ Repository   <context:compenent-scan  base-package="">

xml:<bean>无参构造器、静态工厂(get方法)。

对象(属性)注入的方式

xml:set方法(<property name  value>)、构造器(<constructor-arg name value>)

注解:Autowired、Resource

Spring中用到的设计模式

答:简单工厂、工厂方法单例模式、适配器、包装器、代理、观察者、策略、模板方法

Spring的优点?

答:1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 
2.可以使用容易提供的众多服务,如事务管理,消息服务等 
3.容器提供单例模式支持 
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能 
5.容器提供了众多的辅助类,能加快应用的开发 
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等 
7.spring属于低侵入式设计,代码的污染极低 
8.独立于各种应用服务器 
9.spring的DI机制降低了业务对象替换的复杂性 
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring 的部分或全部 

Spring 的自动装配

https://www.cnblogs.com/xiaolovewei/p/9424804.html

byName/byType/constructor

我们在xml中注入对象,使用<property>属于手动装配,自动装配不需要写这个。如byName,类中对象的属性名与bean的名字一样(id)则直接注入。

Autowired和Resource

https://www.cnblogs.com/xiaolovewei/p/9424856.html

Autowired默认使用byType,单例没问题,Spring的注解。如果想使用byName,则和Qualifier("")一起使用。

Resource(name="")默认byName。J2EE的注解

Spring保证安全性

首先,Controller、Dao、service都是单例的,就有可能出现多线程的安全问题----有类成员变量,这样多线程访问就会使用到共享变量了。

避免:不要使用类成员变量,这样就不会有共享变量了。或者使用ThreadLocal

         使用多例,scope="property"。这样每个线程都有自己的对象,就不会出现问题。

 SpringMVC理解

spring MVC 其实就是 spring 自己做了一套很合适的 controller层 框架。结合性更好。 这个东西的核心就是 Dispatcher(可以理解成一个servlet),根据配置映射的JSP文件路径进行跳转。controller层也可以使用annotation(注解)的方式来描述。MVC的中的C。

 SpringMVC流程(原理)

1 用户发送请求至前端控制器DispatcherServlet;

2 前端控制器调用处理器映射器HandlerMapping,处理器映射器根据URL找到具体的处理器(Handler,也就是Controller),并返回给前端控制器。

3 前端控制器通过处理器适配器HandlerAdapter调用处理器。

4  执行处理器(Controller),执行完后返回给前端控制器一个ModelAndView

5 前端控制器调用视图解析器ViewResolver解析视图,并返回View给前端控制器。

6 前端控制器渲染并显示视图。

 SpringMVC优点

 1. 可以任意使用各种视图技术,而不仅仅局限于JSP

2. 支持各种请求资源的映射策略

3 .它应是易于扩展的

SpringMVC对请求的拦截方式

<servlet-mapping> 中的<url-pattern>/<url-pattern>。/代表拦截所有请求,包括静态资源。 .action拦截对应action结尾的路径,不会拦截静态资源。

对于/,解决静态资源不被拦截的方法:<mvc:resource location="/WEB-INF/js/" mapping="/js/**">  所有对mapping的访问,都转到location位置。

<mvc:annotation-driven>

springmvc需要配置HandlerMapping、HandlerAdapter、ViewResolver。而<mvc:annotation-driven>会自动配置RequestMappingHandlerMapping和RequestMaappingHandlerAdapter。

 

MyBatis

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

Mybatis解决jdbc编程的问题

1、  数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。

2、  Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

3、  向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

4、  对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

 

Mapper接口开发的一些规范

1.mapper.xml中的namespace和mapper接口类路径相同;

2.mapper.xml中的SQL对应的id与mapper接口的方法名相同;

3.mapper.xml中的每个sql的parameterType和接口的输入参数类型相同;

4.mapper.xml中的每个sql的resultType要与接口的返回参数类型相同

#{name}获取parameterType中的属性的值,若输入对象,name就是对应的字段,输入hashmap,name就是key。

resultType总结:

resultType中对象的字段名和查询出来的结果的字段名相同。

返回单个pojo对象要保证sql查询出来的结果集为单条,内部使用sqlsession.selectOne方法调用,mapper接口使用pojo对象作为方法返回值。

 返回pojo列表表示查询出来的结果集可能为多条,内部使用sqlsession.selectList方法,mapper接口使用List<pojo>对象作为方法返回值。

resultMap

如果sql查询字段名和对象的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中

resultMap处理关联查询返回的结果

 一对一:类中除了基本的属性,还包含其他对象,orders中含有User,使用association标签

<resultMap type="cn.itcast.mybatis.po.Orders" id="userordermap">
<!-- 这里的id,是mybatis在进行一对一查询时将user字段映射为user对象时要使用,必须写 -->
    <id property="id" column="id"/>
    <result property="user_id" column="user_id"/>
    <result property="number" column="number"/>
    <association property="user" javaType="cn.itcast.mybatis.po.User">
    <!-- 这里的id为user的id,如果写上表示给user的id属性赋值 -->
        <id property="id" column="user_id"/>
        <result property="username" column="username"/>
        <result property="address" column="address"/>
    </association>
</resultMap>

一对多:类中除了基本的属性外,还包含对象的集合,orders中含有List<Orderdetail>。使用collection标签

<resultMap type="cn.itcast.mybatis.po.Orders" id="userorderdetailmap">
<id property="id"column="id"/>
<result property="user_id" column="user_id"/>
<result property="number" column="number"/>
<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
    <id property="id" column="orderdetail_id"/>
    <result property="items_id" column="items_id"/>
    <result property="items_num" column="items_num"/>
</collection>
</resultMap>

多对多:User中包含List<Orders>,Orders中包含List<Orderdetail>。collection中嵌套collection。

MyBatis延迟加载

查询关联信息时(需要关联对象,要查关联表),首次查询只查询主要信息(单表查询),关联信息等用户获取时再查询(需要查询关联表),大大缓解了数据库压力。association和collection都具备延迟加载的功能。

这个跟 自己在做项目时一样,先查询单表,如果还需要其他表关联信息,再查询其他表。

sqlmapconfig.xml中

 <settings>
     <!--开启延迟加载-->
     <setting name="lazyLoadingEnabled" value="true"/>
     <!--关闭积极加载-->
     <setting name="aggressiveLazyLoading" value="false"/>
 </settings>
 <!--查询订单和创建订单的用户,使用延迟加载-->
 <resultMap id="OrderAndUserLazyLoad" type="Orders">
     <id column="id" property="id"/>
     <result column="user_id" property="userId" />
     <result column="number" property="number" />
     <result column="createtime" property="createtime" />
     <result column="note" property="note" />
     <!--
     select:要延迟加载的statement的id
     colunm:关联两张表的那个列的列名
      -->
     <association property="user" javaType="User" select="findUser" column="user_id">
<--select中就是延迟加载再去执行的sql-->
     </association>
 </resultMap>
 <select id="findOrdersByLazyLoad" resultMap="OrderAndUserLazyLoad">
     SELECT * FROM orders
 </select>

 <select id="findUser" parameterType="int" resultType="User">
     SELECT * FROM User WHERE id = #{value}
 </select>

从上面看,其实就是单表查询两次。

Mybatis缓存

Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。当遇到增删改时会清空缓存。Mybatis默认开启一级缓存。

Mybatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当遇到增删改时会清空缓存。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。

#{}和${}的区别

#{}是预编译处理,${}是字符串替换。 Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值; Mybatis在处理${}时,就是把${}替换成变量的值。 使用#{}可以有效的防止SQL注入,提高系统安全性。

当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

1。查询语句中,给字段名取别名。

2.。resultMap

模糊查询like语句该怎么写?

1.在Java代码中写。string wildcardname = “%smi%”;    list<name> names = mapper.selectlike(wildcardname);

2.Java代码中传入变量,SQL语句中拼接通配符,会引起SQL注入。select * from foo where bar like "%"${value}"%"

mapper如何传递多个参数

1.包装成pojo对象。

2.map

Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;毕竟namespace不是必须的,只是最佳实践而已。

通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

        Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象。

        Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。

        Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

 

posted on 2018-08-05 10:06  夜的第八章  阅读(271)  评论(0编辑  收藏  举报

导航