Ⅳ.数据库


  数据库三范式:1NF 属性不可分 ;2NF 非主键属性,完全依赖于主键属性 ;3NF 非主键属性无传递依赖。

数据库名词解释:

  事务:事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。

  锁:在所以的DBMS中,锁是实现事务的关键,锁可以保证事务的完整性和并发性。与现实生活中锁一样,它可以使某些数据的拥有者,在某段时间内不能使用某些数据或数据结构。当然锁还分级别的。

  视图:视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。

  游标:是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要。

 索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。

根据阿里巴巴的《Java开发手册》中提到的几点注意事项:
1.表名、字段名必须使用小写字母或数字。因为Mysql在Windows下不区分大小写,在Linux下区分。

2.建任何一个表都必须有的三字段:id、gmt_create、gmt_modified(更新表记录时必须同时更新修改时间)。

3.业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。索引会影响insert速度,但实践中损耗可以忽略,但查找速度会显著提升。

4.使用索引时严禁左模糊或者全模糊。因为索引给予B+树实现,具有最左前缀匹配特性,如果左边值未确定,则无法使用索引。同理,使用组合索引时,区分度高的放左边。

索引最左前缀原则(复合索引中要用到索引必须包含建立索引时最左的字段 如建立:(a,b,c)索引,那么在下面三种情况下可以用到:a或a b或a b c。 如果是查b或c这样的就用不到该索引了)

5.强制禁止使用外键和级联!一切外键概念必须在应用层解决。外键和级联更新适合于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库插入速度。

6.强制禁止使用存储过程。存储过程难以调试和拓展,更没有移植性。

7.数据订正(如删除、修改数据)前一定要先select,防止出现误删。

1,数据库索引怎么实现的?

  回答闪光点:b树和b+树,原理,之后加分点是项目中怎么使用,比如使用数据库的主键b树索引 ,并且外键上加入索引,方便查询,防止全表扫描。

  如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。这里我们就为目录id创建了一个索引。

CREATE INDEX mytable_categoryid ON mytable (category_id);

优缺点:
  建立索引的目的是加快对表中记录的查找或排序。为表设置索引要付出代价的:一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。数据库索引就是为了提高表的搜索效率而对某些字段中的值建立的目录 。

  索引有B+索引和hash索引,各自的区别:hash索引,等值查询效率高,不能排序,不能进行范围查询;B+索引,数据有序,范围查询。

  索引底层实现用B+树而不用红黑树和B树,因为增加,删除,红黑树会进行频繁的调整,来保证红黑树的性质,浪费时间 。B树,查询性能不稳定,查询结果高度不致。
索引分类:

  普通索引:最基本的索引,没有任何限制
  唯一索引:与”普通索引”类似,不同的就是:索引列的值必须唯一,但允许有空值。
  主键索引:它是一种特殊的唯一索引,不允许有空值。
  全文索引:针对较大的数据,生成全文索引很耗时好空间。

索引为何能加快查询速度?

等于查一个比较小的表

索引和表都是以数据块的形式存储,但是二者存储结构不同。索引是b-tree结构的一组有序的数据,里面存放的是 key值和行地址(oracle 是rowid)。比如一张表中id字段,有1-100 行,查询id=5这行,那么只需要遍历B-tree树,找到5这个节点,就可以确定一行。但是如果没有索引,就需要遍历整个表的数据块,来确定id=5的这一行。遍历有序的b-tree数据块,确定此行所在位置之后,再一次读取数据,比扫描表所有数据块要快很多效率:几次少量的I/O>全表扫描I/O所以在表数据量特别大的情况下,有无索引提升的性能非常明显,如果表数据就几行,那么索引提升的查询效率就不那么明显了。

介绍一些索引失效的例子?

索引并不是时时都会生效的,比如以下几种情况,将导致索引失效:

1.如果条件中有or,即使其中有部分条件带索引也不会使用(这也是为什么尽量少用or的原因),
注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引

2.对于多列索引,不是使用的第一部分,则不会使用索引

3.like查询是以%开头

4.存在索引列的数据类型隐形转换,则用不上索引,比如列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引

5.where 子句里对索引列上有数学运算或使用函数的,用不上索引

6.如果mysql估计使用全表扫描要比使用索引快,则不使用索引

主键索引和非主键索引的区别

1)主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键; 2)主键不允许为空值,唯一索引列允许空值; 3)一个表只能有一个主键,但是可以有多个唯一索引; 4)主键可以被其他表引用为外键,唯一索引列不可以; 5)主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者有本质的差别

什么情况数据库有索引查找却没用到索引?

2,数据库优化?

  回答闪光点:水平切分,垂直切分,使用索引,怎么防止索引失效,使用缓存,redis等。前面列举的,都需要知道什么意思,并且比如水平切分,在数据库怎么实现的,可以说,表的结构在项目中设计时,都是把一类一类放在一起。比如学生的信息放在一个表等等?

  1.关于select * from t ,用具体的字段代替*;

  2.建表时,首先考虑在where和order by 涉及的列上建立索引,尽量用varchar代替char,只包含数值的字段用数字型字段,避免使用字符型

3,项目怎么设计的,怎么使用数据库的?

回答闪光点:运用了,第一范式,第二范式,第三范式...等等,然后结合项目说,具体怎么用的。

4,数据库的四种连接方式?

按常理会给你出题,让你手写sql。
  1) 内连接 : 相当于select a.,b. from a,b where a.id = b.id
select a.,b. from a inner join b on a.id=b.parent_id

  2)左连接 : 左表的挨个信息去查询,查不到则将右边控制为null进行显示
select a.,b. from a left join b on a.id=b.parent_id

  3) 右连接 : 右表的挨个信息去查询,查不到则将左边控制为null进行显示
select a.,b. from a right join b on a.id=b.parent_id

  4) 完全连接 : 相当于左连接右连接的并集
select a.,b. from a full join b on a.id=b.parent_id

5,数据库的特性,隔离级别,什么是脏读,不可重复读,幻读等等。

回答闪光点:举例说明隔离级别的区别。

这三者都是数据库事务的错误情况。

  脏读:事务A读到了事务B未提交的数据。

  不可重复读:事务A第一次查询得到一行记录row1,事务B提交修改后,事务A第二次查询得到row1,但列内容发生了变化。

  幻读:事务A第一次查询得到一行记录row1,事务B提交修改后,事务A第二次查询得到两行记录row1和row2。

6、MySQL,limit分页如何保证可靠性

  limit在mysql语句中使用的频率非常高,一般分页查询都会使用到limit语句.

  在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能。LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须 是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回 记录行的最大数目。如果只给定一个参数,它表示返回最大的记录行数目.

 mysql的limit给分页带来了极大的方便,但数据量一大的时候,limit的性能就急剧下降。优化方式:(1)使用记录主键的方式进行优化;(2)使用子查询进行查询: (3) 使用between关键字.

7、数据库连接池是为了解决什么问题

  对于高并发的后台服务器来说,频繁的创建和断开连接会降低处理问题的效率。于是我们在客户端和服务器之间事先创建若干连接,并提前放置在连接池中,需要时先从连接池直接获取,数据传输完成后,把连接归还至连接池中(类似与Cache高速缓存,都是以内存换时间的策略),从而提高速度。

  连接资源在数据库端是一种非常关键且有限的资源。资源分配过多会影响数据库性能,分配过少无法完全发挥连接池优势。于是合理的创建、管理、断开连接就十分重要。然后就是阿里开源的Druid能帮你解决这方面问题,详情请见Druid

8、Mysql的数据库引擎,区别特点

  MyISAM:默认的MySQL插件式存储引擎,它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。注意,通过更改STORAGE_ENGINE配置变量,能够方便地更改MySQL服务器的默认存储引擎。

  InnoDB:用于事务处理应用程序,具有众多特性,包括ACID事务支持。(提供行级锁)

  BDB:可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其他事务特性。

  Memory:将所有数据保存在RAM中,在需要快速查找引用和其他类似数据的环境下,可提供极快的访问。

  Merge:允许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一起,并作为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合。

9、对高负载有了解么

  代码出了问题,导致CPU满负载运行,用不了多久就会崩掉。方法一般是先查找到相应进程,kil掉,分析问题代码。相应的就有负载均衡服务。

10、对高并发有了解么?

  连接池、乐观锁、悲观锁、消息队列就是用来解决高并发,即同时很多用户对数据库进行操作。

12、数据库的索引?mysql不同引擎索引的区别

13、数据库的隔离级别

  所谓隔离级别(Isolation Level),就是在数据库事务中,为保证并发数据读写的正确性而提出 的定义,它并不是 MySQL 专有的概念,而是源于ANSI/ISO制定的SQL-92标准。
每种关系型数据库都提供了各自特色的隔离级别实现,虽然在通常的定义中是以锁为实现单元, 但实际的实现千差万别。以最常见的 MySQL InnoDB 引擎为例,它是基于MVCC(MultiVersioning Concurrency Control)和锁的复合实现,按照隔离程度从低到高,MySQL 事务隔 离级别分为四个不同层次:
  读未提交(Read uncommitted),就是一个事务能够看到其他事务尚未提交的修改,这是 最低的隔离水平,允许脏读出现。
  读已提交(Read committed),事务能够看到的数据都是其他事务已经提交的修改,也就 是保证不会看到任何中间性状态,当然脏读也不会出现。读已提交仍然是比较低级别的隔 离,并不保证再次读取时能够获取同样的数据,也就是允许其他事务并发修改数据,允许不 可重复读和幻象读(Phantom Read)出现。
  可重复读(Repeatable reads),保证同一个事务中多次读取的数据是一致的,这是 MySQL InnoDB 引擎的默认隔离级别,但是和一些其他数据库实现不同的是,可以简单认为 MySQL 在可重复读级别不会出现幻象读。
  串行化(Serializable),并发事务之间是串行化的,通常意味着读取需要获取共享读锁,更 新需要获取排他写锁,如果 SQL 使用 WHERE 语句,还会获取区间锁(MySQL 以 GAP 锁 形式实现,可重复读级别中默认也会使用),这是最高的隔离级别。
  至于悲观锁和乐观锁,也并不是 MySQL 或者数据库中独有的概念,而是并发编程的基本概念。 主要区别在于,操作共享数据时,“悲观锁”即认为数据出现冲突的可能性更大,而“乐观 锁”则是认为大部分情况不会出现冲突,进而决定是否采取排他性措施。
  反映到 MySQL 数据库应用开发中,悲观锁一般就是利用类似 SELECT … FOR UPDATE 这样的 语句,对数据加锁,避免其他事务意外修改数据。乐观锁则与 Java 并发包中的 AtomicFieldUpdater 类似,也是利用 CAS 机制,并不会对数据加锁,而是通过对比数据的时 间戳或者版本号,来实现乐观锁需要的版本判断。
  我认为前面提到的 MVCC,其本质就可以看作是种乐观锁机制,而排他性的读写锁、双阶段锁 等则是悲观锁的实现。有关它们的应用场景,你可以构建一下简化的火车余票查询和购票系统。同时查询的人可能很 多,虽然具体座位票只能是卖给一个人,但余票可能很多,而且也并不能预测哪个查询者会购 票,这个时候就更适合用乐观锁。

14、什么是一致性

  数据库一致性(Database Consistency)是指事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。保证数据库一致性是指当事务完成时,必须使所有数据都具有一致的状态。在关系型数据库中,所有的规则必须应用到事务的修改上,以便维护所有数据的完整性。

  数据库实现的场景中,一致性可以分为数据库外部的一致性和数据库内部的一致性。前者由外部应用的编码来保证,即某个应用在执行转帐的数据库操作时,必须在
同一个事务内部调用对帐户A和帐户B的操作。如果在这个层次出现错误,这不是数据库本身能够解决的,也不属于我们需要讨论的范围。后者由数据库来保证,即
在同一个事务内部的一组操作必须全部执行成功(或者全部失败)。这就是事务处理的原子性。

15、什么是隔离性

  为了保证并发情况下的一致性,引入了隔离性,即保证每一个事务能够看到的数据总是一致的,就好象其它并发事务并不存在一样。用术语来说,就是多个事务并发执行后的状态,和它们串行执行后的状态是等价的。怎样实现隔离性,已经有很多人回答过了,原则上无非是两种类型的锁:

  一种是悲观锁,即当前事务将所有涉及操作的对象加锁,操作完成后释放给其它对象使用。为了尽可能提高性能,发明了各种粒度(数据库级/表级/行级……)/各种性质(共享锁/排他锁/共享意向锁/排他意向锁/共享排他意向锁……)的锁。为了解决死锁问题,又发明了两阶段锁协议/死锁检测等一系列的技术。

  一种是乐观锁,即不同的事务可以同时看到同一对象(一般是数据行)的不同历史版本。如果有两个事务同时修改了同一数据行,那么在较晚的事务提交时进行冲突检测。

18、数据库挂了怎么办

  每天定时备份,挂了重启。

19、数据库的瓶颈

  大部分数据库瓶颈是在高并发。同时很多人访问数据库。

 一、缓存式的Web应用程序架构:

  在Web层和db层之间加一层cache层,主要目的:减少数据库读取负担,提高数据读取速度。cache存取的媒介是内存,可以考虑采用分布式的cache层,这样更容易破除内存容量的限制,同时增加了灵活性。

  二、实现MySQL数据库异步查询实现:

  通常情况下在PHP中MySQL查询是串行的,如果能实现MySQL查询的异步化,就能实现多条SQL语句同时执行,这样就能大大地缩短MySQL查询的耗时,提高数据库查询的效率。

  三、MySQL主从读写分离:

  当数据库的写压力增加,cache层(如Memcached)只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负。使用主从复制技术(master-slave模式)来达到读写分离,以提高读写性能和读库的可扩展性。读写分离就是只在主服务器上写,只在从服务器上读,基本原理是让主数据库处理事务性查询,而从数据库处理select查询,数据库复制被用于把事务性查询(增删改)导致的改变更新同步到集群中的从数据库。

20.当你执行一条SQL语句,背后执行的过程是什么样的?

https://zhuanlan.zhihu.com/p/50668097

21.SQL语句调优会吗,有哪些调优方式

性能调优的目的主要有以下两点:

1.优化响应时间

2.优化吞吐量

https://zhuanlan.zhihu.com/p/33019910

Ⅴ.设计模式

  设计模式是人们为软件开发中相同表征的问题,抽象出的可重复利用的解决方案。在某种程度 上,设计模式已经代表了一些特定情况的最佳实践,同时也起到了软件工程师之间沟通的“行话”的作用。理解和掌握典型的设计模式,有利于我们提高沟通、设计的效率和质量。
相关链接

1、谈谈你知道的设计模式?

大致按照模式的应用目标分类,设计模式可以分为创建型模式、结构型模式和行为型模式。

  创建型模式,是对对象创建过程的各种问题和解决方案的总结,包括各种工厂模式 (Factory、Abstract Factory)、单例模式(Singleton)、构建器模式(Builder)、原型 模式(ProtoType)。

  结构型模式,是针对软件设计结构的总结,关注于类、对象继承、组合方式的实践经验。常 见的结构型模式,包括桥接模式(Bridge)、适配器模式(Adapter)、装饰者模式 (Decorator)、代理模式(Proxy)、组合模式(Composite)、外观模式(Facade)、 享元模式(Flyweight)等。

  行为型模式,是从类或对象之间交互、职责划分等角度总结的模式。比较常见的行为型模式 有策略模式(Strategy)、解释器模式(Interpreter)、命令模式(Command)、观察者 模式(Observer)、迭代器模式(Iterator)、模板方法模式(Template Method)、访问 者模式(Visitor)。

2、讲一下你项目中用到了哪些设计模式

比如:
  IO 框架,我们知道 InputStream 是一个抽象类,标准类库中提供 了 FileInputStream、ByteArrayInputStream 等各种不同的子类,分别从不同角度对 InputStream 进行了功能扩展,这是典型的装饰器模式应用案例。

  因为装饰器模式本质上是包装同类型实例,我们对目标对象的调用,往往会通过包装类覆盖过的 方法,迂回调用被包装的实例,这就可以很自然地实现增加额外逻辑的目的,也就是所谓的“装 饰”。

看主流开源框架,如 Spring 等如何在 API 设计中使 用设计模式。你至少要有个大体的印象,如:

  BeanFactory和ApplicationContext应用了工厂模式。
  在 Bean 的创建中,Spring 也为不同 scope 定义的对象,提供了单例和原型等模式实现。
  AOP 领域则是使用了代理模式、装饰器模式、适配器模式等。
  各种事件监听器,是观察者模式的典型应用。
  类似 JdbcTemplate 等则是应用了模板模式

3、写一个单例模式,答主写的是双检查锁单例,问了为什么用Volatile,synchronize移到方法最外面会怎么样?

  我们来实现一个日常非常熟悉的单例设计模式。看起来似乎很简单,那么下面这个样例符合基本 需求吗?
  第一版单例模式:

public class Singleton {        
     private static Singleton instance = new Singleton();       
     public static Singleton getInstance() {           
         return instance;        
     }     
 }

  然而Java 会自动为没有明确声明构造函数的类,定义一个 public 的无参数的构造函数,所以上面的例子并不能保证额外的对象不被创建出来,别人完全可以直 接“new Singleton()”,那我们应该怎么处理呢?答案是,我们可以为单例定义一个 private 的构造函数(也有建议声明为枚举,这是有争议的,我个人 不建议选择相对复杂的枚举,毕竟日常开发不是学术研究)。这样还有什么改进的余地吗?在 ConcurrentHashMap 那里,我们提到过标准类库中很多地方使用懒加载(lazyload),改善初始内存开销,单例同样适用,下面是修正后的改进版本。

  第二版单例模式(加private的构造函数、懒加载)

public class Singleton {         
    private static Singleton instance;         
    private Singleton() {         
    }         
    public static Singleton getInstance() { 
        if (instance == null) {             
            instance = new Singleton();             
        }        
        return instance;        
    }     
}

  这个实现在单线程环境不存在问题,但是如果处于并发场景,就需要考虑线程安全,最熟悉的就莫过于“双检锁”,其要点在于:这里的 volatile 能够提供可见性,以及保证 getInstance 返回的是初始化完全的对象。在同步之前进行 null 检查,以尽量避免进入相对昂贵的同步块。直接在 class 级别进行同步,保证线程安全的类方法调用。

  第三版单例模式(加volatile,synchronize,并且是在类里面加,为的是避免进入同步块同步,而是直接在.class级别同步)

public class Singleton {     
    private static volatile Singleton singleton = null;     
    private Singleton() {     
    } 

    public static Singleton getSingleton() {         
        if (singleton == null) { // 尽量避免重复进入同步块             
            synchronized (Singleton.class) { // 同步.class,意味着对同步类方法调用         
                if (singleton == null) {                     
                singleton = new Singleton();                
                }            
            }        
        }        
        return singleton;     
    } 
} 

  在这段代码中,争论较多的是 volatile 修饰静态变量,当 Singleton 类本身有多个成员变量 时,需要保证初始化过程完成后,才能被 get 到。所以,可以看出,即使是看似最简单的单例模式,在增加各种高标准需求之后,同样需要非常多 的实现考量。上面是比较学究的考察,其实实践中未必需要如此复杂,如果我们看 Java 核心类库自己的单例 实现,比如java.lang.Runtime,你会发现:它并没使用复杂的双检锁之类。静态实例被声明为 final,这是被通常实践忽略的,一定程度保证了实例不被篡改(专栏第 6 讲介绍过,反射之类可以绕过私有访问限制),也有有限的保证执行顺序的语义。

private static final Runtime currentRuntime = new Runtime();
private static Version version; 
// … 
public static Runtime getRuntime() {    
    return currentRuntime; 
} 
/** Don't let anyone else instantiate this class */ 
private Runtime() {} 

  PS:基于《阿里巴巴Lava开发手册》。强制规定,获取单例对象需保证线程安全,其中的方法也要保证线程安全。资源驱动类、工具类、单例工厂类都需要注意。
Java源码在线查看地址

4、抽象工厂和工厂方法模式的区别

  工厂模式例子

public class VIPCenter {   
    void serviceVIP(T extend User user>) {      
        if (user instanceof SlumDogVIP) {         // 穷 X VIP,活动抢的那种         
            // do somthing       
        } else if(user instanceof RealVIP) {        
            // do somthing       
        }       
        // ...  
    } 

  这段代码的一个问题是,业务逻辑集中在一起,当出现新的用户类型时,比如,大数据发现了我 们是肥羊,需要去收获一下, 这就需要直接去修改服务方法代码实现,这可能会意外影响不相 关的某个用户类型逻辑。

  利用开关原则,我们可以尝试改造为下面的代码:

public class VIPCenter {    
    private Map<User.TYPE, ServiceProvider> providers;    
    void serviceVIP(T extend User user) {       providers.get(user.getType()).service(user);    
    }  
} 
 interface ServiceProvider{    
     void service(T extend User user) ;  
 } 
class SlumDogVIPServiceProvider { 
     void service(T extend User user){      
         // do somthing   
     } 
} 
class RealVIPServiceProvider{    
    void service(T extend User user) {      
        // do something    
    }  
}

  上面的示例,将不同对象分类的服务方法进行抽象,把业务逻辑的紧耦合关系拆开,实现代码的 隔离保证了方便的扩展。即是把简单工厂模式修改为工厂方法模式。原来的违反了开闭选择, 工厂方法模式刚好弥补了这个问题,倒是相应的系统中的类个数也成对的增加。设计模式没 有优的,只是特定场景下我们选择相对优良的模式来优化我们的逻辑。

5、工厂模式的思想

  工厂模式:为创建对象提供过度接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

VI.框架

1、介绍一下springMVC,springMVC的特性有哪些

  首先是一个MVC框架。在web模型中,MVC是一种很流行的框架,通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,是为了简化开发,减少出错。还是为了组内开发人员之间的配合。总之就是一种分层工作的办法。其次,springMVC,是spring的一个子框架,当然拥有spring的特性,如依赖注入。

1、ioc,实现java bean的低耦合性,便于java code 的重用;
2、aop使用简便;
3、实现restful的mvc,便于web开发;
4、大量的注解pojo,简化了xml配置;
5、database的dao模板类,兼容多种数据库,而且底层只需要更换jdbc driver,datasource声明好驱动,jdbctemplate就可以访问数据库了;
6、spring官网有很多解决方案可以使用(安全,数据访问,页面流,android)

  总之spring很好的实现了系统的低耦合高聚合,便于代码的重用,而且面向接口的编程可以让api的访问不用知道底层的实现(如jdbctemplate,它并不知道是访问什么类型的数据库,只是配置上的差异,这样以后想从mysql换到oracle只需要换下驱动就好了,dao代码都不用改)

2、spring如何管理bean、bean的生命周期

  Spring Bean 生命周期比较复杂,可以分为创建和销毁两个过程。
    首先,创建 Bean 会经过一系列的步骤,主要包括:
    实例化 Bean 对象。
    设置 Bean 属性。

  如果我们通过各种 Aware 接口声明了依赖关系,则会注入 Bean 对容器基础设施层面的依 赖。具体包括 BeanNameAware、BeanFactoryAware 和 ApplicationContextAware,分 别会注入 Bean ID、Bean Factory 或者 ApplicationContext。调用 BeanPostProcessor 的前置初始化方法 postProcessBeforeInitialization。如果实现了 InitializingBean 接口,则会调用 afterPropertiesSet 方法。调用 Bean 自身定义的 init 方法。调用 BeanPostProcessor 的后置初始化方法 postProcessAfterInitialization。创建过程完毕。
  
 你可以参考下面示意图理解这个具体过程和先后顺序。

  第二,Spring Bean 的销毁过程会依次调用 DisposableBean 的 destroy 方法和 Bean 自身定 制的 destroy 方法。

  Spring Bean 有五个作用域,其中基础的有下面两种:
  Singleton,这是 Spring 的默认作用域,也就是为每个 IOC 容器创建唯一的一个 Bean 实 例。
  Prototype,针对每个 getBean 请求,容器都会单独创建一个 Bean 实例。
  从 Bean 的特点来看,Prototype 适合有状态的 Bean,而 Singleton 则更适合无状态的情况。 另外,使用 Prototype 作用域需要经过仔细思考,毕竟频繁创建和销毁 Bean 是有明显开销 的。
  如果是 Web 容器,则支持另外三种作用域:
    Request,为每个 HTTP 请求创建单独的 Bean 实例。
    Session,很显然 Bean 实例的作用域是 Session 范围。
    GlobalSession,用于 Portlet 容器,因为每个 Portlet 有单独的 Session,GlobalSession 提供一个全局性的 HTTP Session。

3、spring管理的bean有哪些模式,spring默认的是哪种模式

  Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系。因此,如果可能的话,可以自动让Spring通过检查BeanFactory中的内容,来替我们指定bean的协作者(其他被依赖的bean)。autowire一共有六种类型。由于autowire可以针对单个bean进行设置,因此可以让有些bean使用autowire,有些bean不采用。autowire的方便之处在减少或者消除属性或构造器参数的设置,这样可以给我们的配置文件减减肥![2] 在xml配置文件中,可以在元素中使用autowire属性指定: Default、 On 、ByNname 、Bytype 、Constructor 、Antodetect。

4、Mybatis和Hibernate的区别,Mybatis如何避免SQL注入

  接下来我们还是回到 Java 本身,目前最为通用的 Java 和数据库交互技术就是 JDBC,最常见的 开源框架基本都是构建在 JDBC 之上,包括我们熟悉的JPA/Hibernate、MyBatis、Spring JDBC Template 等,各自都有独特的设计特点。具体原因是在持久层的开发过程中,因为使用原生JDBC太过繁琐(每次都要进行加载驱动,获得链接,编写statement,解析result,封装数据),导致开发速度缓慢。虽然在后来也有对应简化方法,比如使用数据库连接池,使用dbUtils等方法,但是都不尽人意。这个时候出现了自动化的ORM框架。

  Hibernate 是最负盛名的 O/R Mapping 框架之一,它也是一个 JPA Provider。顾名思义,它 是以对象为中心的,其强项更体现在数据库到 Java 对象的映射,可以很方便地在 Java 对象层 面体现外键约束等相对复杂的关系,提供了强大的持久化功能。内部大量使用了Lazy-load等技 术提高效率。并且,为了屏蔽数据库的差异,降低维护开销,Hibernate 提供了类 SQL 的 HQL,可以自动生成某种数据库特定的 SQL 语句。

  Hibernate 应用非常广泛,但是过度强调持久化和隔离数据库底层细节,也导致了很多弊端,例 如 HQL 需要额外的学习,未必比深入学习 SQL 语言更高效;减弱程序员对 SQL 的直接控制, 还可能导致其他代价,本来一句 SQL 的事情,可能被 Hibernate 生成几条,隐藏的内部细节也 阻碍了进一步的优化。而 MyBatis 虽然仍然提供了一些映射的功能,但更加以 SQL 为中心,开发者可以侧重于 SQL 和存储过程,非常简单、直接。如果我们的应用需要大量高性能的或者复杂的 SELECT 语句 等,“半自动”的 MyBatis 就会比 Hibernate 更加实用。

  而 Spring JDBC Template 也是更加接近于 SQL 层面,Spring 本身也可以集成 Hibernate 等 O/R Mapping 框架。

  什么是mybatis

  它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
为什么使用mybatis

  相对于原生JDBC而言使用mybatis可以简化大部分的重复编码,相对于hibernate(ORM)框架而言mybatis更加轻量,更加容易进行调整,也拥有更加快的速度。在出现问题的时候也更容易排查。总而言之在追求效率和快速变化的业务场景下,选择mybatis可以给你带来更好的开发体验。

5、JDBC用了哪种模式

6、Spring Boot 和 Spring Clould区别

  1、Spring boot 是 Spring 的一套快速配置脚手架,可以基于spring boot 快速开发单个微服务;Spring Cloud是一个基于Spring Boot实现的云应用开发工具;

  2、Spring boot专注于快速、方便集成的单个个体,Spring Cloud是关注全局的服务治理框架;

  3、spring boot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring boot来实现。

  4、Spring boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring boot,属于依赖的关系。

7、Spring 和 Spring MVC区别

  Spring的两大核心AOP与IOC,可以单独用于任何应用,包括与Struts等MVC框架与Hibernate等ORM框架的集成,目前很多公司所谓的轻量级开发就是用 Spring + Struts(2)+Hibernate。
Spring MVC就是一个MVC框架,个人觉得Spring MVC annotation式的开发比Struts2方便,可以直接代替上面的Struts(当然Struts的做为一个非常成熟的MVC,功能上感觉还是比Spring强一点,不过Spring MVC已经足够用了)。当然spring mvc的执行效率比struts高,是因为struts的值栈影响效率。spring mvc类似于struts的一个MVC开框架,其实都是属于spring,spring mvc需要有spring的架包作为支撑才能跑起来

8、你对IOC的理解

  要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想:依赖倒置原则(Dependency Inversion Principle )

 什么是依赖倒置原则?假设我们设计一辆汽车:先设计轮子,然后根据轮子大小设计底盘,接着根据底盘设计车身,最后根据车身设计好整个汽车。这里就出现了一个“依赖”关系:汽车依赖车身,车身依赖底盘,底盘依赖轮子。
 这样的设计看起来没问题,但是可维护性却很低。假设设计完工之后,上司却突然说根据市场需求的变动,要我们把车子的轮子设计都改大一码。这下我们就蛋疼了:因为我们是根据轮子的尺寸设计的底盘,轮子的尺寸一改,底盘的设计就得修改;同样因为我们是根据底盘设计的车身,那么车身也得改,同理汽车设计也得改——整个设计几乎都得改!
我们现在换一种思路。我们先设计汽车的大概样子,然后根据汽车的样子来设计车身,根据车身来设计底盘,最后根据底盘来设计轮子。这时候,依赖关系就倒置过来了:轮子依赖底盘, 底盘依赖车身, 车身依赖汽车。这时候,上司再说要改动轮子的设计,我们就只需要改动轮子的设计,而不需要动底盘,车身,汽车的设计了。这就是依赖倒置原则——把原本的高层建筑依赖底层建筑“倒置”过来,变成底层建筑依赖高层建筑。高层建筑决定需要什么,底层去实现这样的需求,但是高层并不用管底层是怎么实现的。这样就不会出现前面的“牵一发动全身”的情况。

  控制反转(Inversion of Control) 就是依赖倒置原则的一种代码设计的思路。具体采用的方法就是所谓的依赖注入(Dependency Injection)。其实这些概念初次接触都会感到云里雾里的。说穿了,这几种概念的关系大概如下:链接

9、Forward和redirect的区别

1.从地址栏显示来说
  forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
  redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.

2.从数据共享来说
  forward:转发页面和转发到的页面可以共享request里面的数据.
  redirect:不能共享数据.

3.从运用地方来说
  forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
  redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.

4.从效率来说
  forward:高.
  redirect:低.

10、 Spring中autowire和resourse关键字的区别

  Autowire按类型装配,resource按名称装配

11、bean的生命周期

12、bean的作用域

   链接

13、介绍spring中的熟悉的注解

  xml、注解和Java Config到底选哪个
 链接

14、让你实现autowire注解的功能你会如何实现

   链接

15、Spring的aop怎么实现

  先问一下自己,我们为什么需要切面编程呢?

  切面编程落实到软件工程其实是为了更好地模块化,而不仅仅是为了减少重复代码。通过 AOP 等机制,我们可以把横跨多个不同模块的代码抽离出来,让模块本身变得更加内聚,进而业务开 发者可以更加专注于业务逻辑本身。从迭代能力上来看,我们可以通过切面的方式进行修改或者 新增功能,这种能力不管是在问题诊断还是产品能力扩展中,都非常有用。
在之前的分析中,我们已经分析了 AOP Proxy 的实现原理,简单回顾一下,它底层是基于 JDK 动态代理或者 cglib 字节码操纵等技术,运行时动态生成被调用类型的子类等,并实例化代理对 象,实际的方法调用会被代理给相应的代理对象。但是,这并没有解释具体在 AOP 设计层面, 什么是切面,如何定义切入点和切面行为呢?

  Spring AOP 引入了其他几个关键概念:

  Aspect,通常叫作方面,它是跨不同 Java 类层面的横切性逻辑。在实现形式上,既可以是 XML 文件中配置的普通类,也可以在类代码中用“@Aspect”注解去声明。在运行时, Spring 框架会创建类似Advisor来指代它,其内部会包括切入的时机(Pointcut)和切入的 动作(Advice)。

  Join Point,它是 Aspect 可以切入的特定点,在 Spring 里面只有方法可以作为 Join Point。

  Advice,它定义了切面中能够采取的动作。如果你去看 Spring 源码,就会发现 Advice、 Join Point 并没有定义在 Spring 自己的命名空间里,这是因为他们是源自AOP 联盟,可以 看作是 Java 工程师在 AOP 层面沟通的通用规范。

  Java 核心类库中同样存在类似代码,例如 Java 9 中引入的 Flow API 就是 Reactive Stream 规 范的小子集,通过这种方式,可以保证不同产品直接的无缝沟通,促进了良好实践的推广。

  具体的 Spring Advice 结构请参考下面的示意图。

  另外,Spring 框架本身功能点非常多,AOP 并不是它所支持的唯一切面技术,它只能利用动态 代理进行运行时编织,而不能进行编译期的静态编织或者类加载期编织。例如,在 Java 平台 上,我们可以使用 Java Agent 技术,在类加载过程中对字节码进行操纵,比如修改或者替换方 法实现等。在 Spring 体系中,如何做到类似功能呢?你可以使用 AspectJ,它具有更加全面的 能力,当然使用也更加复杂。

16、Spring的aop有哪些实现方式

  1.经典的基于代理的AOP

  2.@AspectJ注解驱动的切面

  3.纯POJO切面

  4.注入式AspectJ切面

链接

17、动态代理的实现方式和区别

   AOP(Aspect-OrientedProgramming,面向切面编程),AOP包括切面(aspect)、通知(advice)、连接点(joinpoint),实现方式就是通过对目标对象的代理在连接点前后加入通知,完成统一的切面操作。

  实现AOP的技术,主要分为两大类:

  一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;

  二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

  Spring提供了两种方式来生成代理对象: JDKProxy和Cglib,具体使用哪种方式生成由AopProxyFactory根据AdvisedSupport对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK动态代理技术,如果目标对象没有实现接口,则默认会采用CGLIB代理。如果目标对象实现了接口,可以强制使用CGLIB实现代理(添加CGLIB库,并在spring配置中加入)。
  链接

18、Hibernate的作用,你的理解

  首先Hibernate不是MVC框架,准确来说是ORM框架。Hibernate的作用完全可以从ORM(Object Relation Mapping)的意思中体现出来。Hibernate工作就是将数据库中的关系型数据映射成Java对象。说白了就是方便开发者使用Java来对关系型数据库进行操作的,这里的重点是关系型数据库,和Nosql种种并无半毛钱关系。优点:有自己的Hql语句,对sql进行了一定的封装;各种关系型数据库基本都能支持;开发难度低;各方面都比较成熟完善,包括事务、缓存等一些ORM该有的东西它都有;缺点:数据量大的时候,Hibernate就虚了,尤其是delete和update操作

  首先hibernate是JPA的一种实现 。hibernate的精髓就是一级缓存。

19、Hibernate和mybatis的区别

21、讲讲你对spring的理解,不要把ioc和aop背给我听

  首先,我们先来看看 Spring 的基础机制,至少你需要理解下面两个基本方面

  控制反转(Inversion of Control),或者也叫依赖注入(Dependency Injection),广泛 应用于 Spring 框架之中,可以有效地改善了模块之间的紧耦合问题。
从 Bean 创建过程可以看到,它的依赖关系都是由容器负责注入,具体实现方式包括带参数的构 造函数、setter 方法或者AutoWired方式实现。

  AOP,我们已经在前面接触过这种切面编程机制,Spring 框架中的事务、安全、日志等功能 都依赖于 AOP 技术,下面我会进一步介绍。

  第二,Spring 到底是指什么?

  我前面谈到的 Spring,其实是狭义的Spring Framework,其内部包含了依赖注入、事件机制 等核心模块,也包括事务、O/R Mapping 等功能组成的数据访问模块,以及 Spring MVC 等 Web 框架和其他基础组件。广义上的 Spring 已经成为了一个庞大的生态系统,例如:Spring Boot,通过整合通用实践,更加自动、智能的依赖管理等,Spring Boot 提供了各种 典型应用领域的快速开发基础,所以它是以应用为中心的一个框架集合。Spring Cloud,可以看作是在 Spring Boot 基础上发展出的更加高层次的框架,它提供了构 建分布式系统的通用模式,包含服务发现和服务注册、分布式配置管理、负载均衡、分布式 诊断等各种子系统,可以简化微服务系统的构建。当然,还有针对特定领域的 Spring Security、Spring Data 等。

22、Hibernate的batch有数量限制么

   有,并且可以在Spring配置中进行修改(否则一般机器十万条数据会崩?)。

VII.完整的项目

十分钟入门——基于SpringBoot的登录demo
一个详细的Spring项目
详细链接
一些面经
1、介绍你的项目
2、项目的设计思路是什么,为什么这么设计。
3、项目设计的难点是什么,怎么解决的。
4、项目怎么实现某某功能的。
5、项目你做了什么优化。
6、数据库做了哪些处理。
7、项目介绍:遇到最大的困难是什么,怎么解决的,你觉得自己的项目哪些地方可以进行优化
8、项目介绍,最复杂的表