zoukankan      html  css  js  c++  java
  • 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执行结果返回。

  • 相关阅读:
    代码审查如何做
    使用 Gitbook 打造你的电子书
    Ztree的简单使用和后台交互的写法(一)
    ORACLE 错误:oralce record is locked by another user
    easyUI增加视图分组的办法
    jquery 解析数据库中的json日期为正常的格式
    Bootstrap基本类和组件学习二
    bootstrap的学习-基础样式和排版一
    easyUI中tree的简单使用
    orancle的安装和配置
  • 原文地址:https://www.cnblogs.com/xiaolovewei/p/9424609.html
Copyright © 2011-2022 走看看