Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内
存分页,而非物理分页。可以在 sql 内直接书写带有物理分页的参数来完成物理分
页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件
的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物
理分页语句和物理分页参数。
#{}是预编译处理,KaTeX parse error: Expected 'EOF', got '#' at position 22: …替换。 Mybatis 在处理#̲{}时,会将 sql 中的#{…{}时,就是把${}替换成变量的值。
使用#{}可以有效的防止 SQL 注入,提高系统安全性。
第 1 种: 通过在查询的 sql 语句中定义字段名的别名,让字段名的别名和实体类
的属性名一致。
第 2 种: 通过来映射字段名和实体类属性名的一一对应的关系。
Dao 接口即 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值;
接口的方法名,就是映射文件中 Mapper 的 Statement 的 id 值;接口方法内的
参数,就是传递给 sql 的参数。
Mapper 接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符
串作为 key 值,可唯一定位一个 MapperStatement。在 Mybatis 中,每一个
、、、标签,都会被解析为一个
MapperStatement 对象。
Mybatis 动态 sql 可以在 Xml 映射文件内,以标签的形式编写动态 sql,执行原理
是根据表达式的值 完成逻辑判断并动态拼接 sql 的功能。
Mybatis 提供了 9 种动态 sql 标签:trim | where | set | foreach | if | choose
| when | otherwise | bind。
1、Mybatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时
只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建
statement 等繁杂的过程。程序员直接编写原生态 sql,可以严格控制 sql 执行性
能,灵活度高。
2、MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数
据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。 3、通过 xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过
java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最
后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。(从执行 sql 到返
回 result 的过程)。
Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key-value 数据库。非关系型数据库
性能极高 – Redis 能读的速度是 110000 次/s,写的速度是 81000 次/s 。
丰富的数据类型 – Redis 支持二进制案例的 Strings, Lists, Hashes, Sets 及
Ordered Sets 数据类型操作。
原子 – Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不
执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC
指令包起来。
丰富的特性 – Redis 还支持 publish/subscribe, 通知, key 过期等等特性。
答:Redis 支持五种数据类型:string(字符串),hash(哈希),list(列表),
set(集合)及 zsetsorted set:有序集合)。
我们实际项目中比较常用的是 string,hash 如果你是 Redis 中高级用户,还需要
加上下面几种数据结构 HyperLogLog、Geo、Pub/Sub。
如果你说还玩过 Redis Module,像 BloomFilter,RedisSearch,Redis-ML,面
试官得眼睛就开始发亮了。
答:Redis 是单进程单线程的,redis 利用队列技术将并发访问变为串行访问,消
除了传统数据库串行控制的开销。
Redis 提供两种持久化机制 RDB 和 AOF 机制:
1、RDBRedis DataBase)持久化方式: 是指用数据集快照的方式半持久化模式)
记录 redis 数据库的所有键值对,在某个时间点将数据写入一个临时文件,持久化
结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。
2、AOFAppend-only file)持久化方式: 是指所有的命令行记录以 redis 命令请
求协议的格式完全持久化存储)保存为 aof 文件
1、Master 最好不要写内存快照,如果 Master 写内存快照,save 命令调度 rdbSave
函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性
暂停服务
2、如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一
3、为了主从复制的速度和连接的稳定性,Master 和 Slave 最好在同一个局域网
4、尽量避免在压力很大的主库上增加从
5、主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1
<- Slave2 <- Slave3…这样的结构方便解决单点故障问题,实现 Slave 对 Master
的替换。如果 Master 挂了,可以立刻启用 Slave1 做 Master,其他不变
1)、Redis Sentinal 着眼于高可用,在 master 宕机时会自动将 slave 提升为
master,继续提供服务。
2)、Redis Cluster 着眼于扩展性,在单个 redis 内存不足时,使用 Cluster 进行
分片存储
异步复制
16384 个。
Redis 集群目前无法做数据库选择,默认在 0 数据库
1、表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最
高,并发度最低。
2、行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最
低,并发度也最高。
3、页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表
锁和行锁之间,并发度一般。
READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读
1、CONCAT(A, B) – 连接两个字符串值以创建单个字符串输出。通常用于将两个
或多个字段合并为一个字段。
2、FORMAT(X, D)- 格式化数字 X 到 D 有效数字。
3、CURRDATE(), CURRTIME()- 返回当前日期或时间。
4、NOW() – 将当前日期和时间作为一个值返回。
5、MONTH(),DAY(),YEAR(),WEEK(),WEEKDAY() – 从日期
值中提取给定数据。
6、HOUR(),MINUTE(),SECOND() – 从时间值中提取给定数据。
7、DATEDIFF(A,B) – 确定两个日期之间的差异,通常用于计算年龄
8、SUBTIMES(A,B) – 确定两次之间的差异。
9、FROMDAYS(INT) – 将整数天数转换为日期值
MySQL 服务器通过权限表来控制用户对数据库的访问,权限表存放在 MySQL 数
据库里,由 MySQL_install_db 脚本初始化。这些权限表分别 user,db,table_priv,
columns_priv 和 host。
预计运维三年,怎么优化?
1、设计良好的数据库结构,允许部分数据冗余,尽量避免 join 查询,提高效率。
2、选择合适的表字段数据类型和存储引擎,适当的添加索引。
3、MySQL 库主从读写分离。
4、找规律分表,减少单表中的数据量提高查询速度。
5、添加缓存机制,比如 memcached,apc 等。
6、不经常改动的页面,生成静态页面。
7、书写高效率的 SQL。比如 SELECT * FROM TABEL 改为 SELECT field_1,
field_2, field_3 FROM TABLE.
1、读写分离
2、分段加锁
3、减少锁持有的时间
4.多个线程尽量以相同的顺序去获取资源
不能将锁的粒度过于细化,不然可能会出现线程的加锁和释放次数过多,反而效
率不如一次加一把大锁。
B+树,经过优化的 B+树
主要是在所有的叶子结点中增加了指向下一个叶子节点的指针,因此 InnoDB 建
议为大部分表使用默认自增的主键作为主索引。
1、以“%”开头的 LIKE 语句,模糊匹配
2、OR 语句前后没有同时使用索引
3、数据类型出现隐式转化(如 varchar 不加单引号的话可能会自动转换为 int 型)
最好是按照以下顺序优化:
1、SQL 语句及索引的优化
2、数据库表结构的优化
3、系统配置的优化
4、硬件的优化
1、选取最适用的字段属性,尽可能减少定义字段宽度,尽量把字段设置 NOTNULL,
例如’省份’、’性别’最好适用 ENUM
2、使用连接(JOIN)来代替子查询
3、适用联合(UNION)来代替手动创建的临时表
4、事务处理
5、锁定表、优化事务处理
6、适用外键,优化锁定表
7、建立索引
8、优化查询语句
事务(transaction)是作为一个单元的一组有序的数据库操作。如果组中的所有
操作都成功,则认为事务成功,即使只有一个操作失败,事务也不成功。如果所
有操作完成,事务则提交,其修改将作用于所有其他数据库进程。如果一个操作
失败,则事务将回滚,该事务所有操作的影响都将取消。
1、原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。
2、一致性或可串性。事务的执行使得数据库从一种正确状态转换成另一种正确状态
3、隔离性。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务,
4、持久性。事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后
有了其他故障,事务的处理结果也会得到保存。
或者这样理解:
事务就是被绑定在一起作为一个逻辑工作单元的 SQL 语句分组,如果任何一个语
句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上
有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作
为事务考虑,就需要通过 ACID 测试,即原子性,一致性,隔离性和持久性。
先说什么是交叉连接: 交叉连接又叫笛卡尔积,它是指不使用任何条件,直接将一
个表的所有记录和另一个表中的所有记录一一匹配。
内连接 则是只有条件的交叉连接,根据某个条件筛选出符合条件的记录,不符合
条件的记录不会出现在结果集中,即内连接只连接匹配的行。
外连接 其结果集中不仅包含符合连接条件的行,而且还会包括左表、右表或两个
表中
的所有数据行,这三种情况依次称之为左外连接,右外连接,和全外连接。
左外连接,也称左连接,左表为主表,左表中的所有记录都会出现在结果集中,
对于那些在右表中并没有匹配的记录,仍然要显示,右边对应的那些字段值以
NULL 来填充。右外连接,也称右连接,右表为主表,右表中的所有记录都会出现
在结果集中。左连接和右连接可以互换,MySQL 目前还不支持全外连接。
存储过程是一个预编译的 SQL 语句,优点是允许模块化的设计,就是说只需
创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次 SQL,
使用存储过程比单纯 SQL 语句执行要快。可以用一个命令对象来调用存储过程
答:第一范式:1NF 是对属性的原子性约束,要求属性具有原子性,不可再分解;
第二范式:2NF 是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;
第三范式:3NF 是对字段冗余性的约束,即任何字段不能由其他字段派生出来,
它要求字段没有冗余。。
定义:
主键–唯一标识一条记录,不能有重复的,不允许为空
外键–表的外键是另一表的主键, 外键可以有重复的, 可以是空值
索引–该字段没有重复值,但可以有一个空值
作用:
主键–用来保证数据完整性
外键–用来和其他表建立联系用的
索引–是提高查询排序的速度
个数:
主键–主键只能有一个
外键–一个表可以有多个外键
索引–一个表可以有多个唯一索引
1、Where 子句中:where 表之间的连接必须写在其他 Where 条件之前,那些可
以过滤掉最大数量记录的条件必须写在 Where 子句的末尾.HAVING 最后。
2、用 EXISTS 替代 IN、用 NOT EXISTS 替代 NOT IN。 3、 避免在索引列上使用计算
4、避免在索引列上使用 IS NULL 和 IS NOT NULL
5、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉
及的列上建立索引。
6、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃
使用索引而进行全表扫描
7、应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用
索引而进行全表扫描
数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供
不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以 获得特定的功能。现在许多不同的数据库管理系统都支持多
种不同的数据引擎。存储引擎主要有: 1. MyIsam , 2. InnoDB, 3. Memory, 4. Archive, 5. Federated 。
索引(Index)是帮助 MySQL 高效获取数据的数据结构。 常见的查询算法,顺序查找,二分查找,二叉排序树查找,哈希散列法,分块查找,平衡多
路搜索树 B 树(B-tree) ,索引是对数据库表中一个或多个列的值进行排序的结构,建立索引有助于快速获取信息。
你也可以这样理解:索引就是加快检索表中数据的方法。数据库的索引类似于书籍的索引。在书籍中,索引允许用户不必翻阅完整个书就能
迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅速地找到表中的数据,而不必扫描整个数据库
mysql 有4种不同的索引:
主键索引(PRIMARY)
唯一索引(UNIQUE)
普通索引(INDEX)
全文索引(FULLTEXT)
内联接(Inner Join):匹配2张表中相关联的记录。
左外联接(Left Outer Join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中未匹配到的字段用NULL表示。
右外联接(Right Outer Join):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配到的字段用NULL表示。在
判定左表和右表时,要根据表名出现在Outer Join的左右位置关系
在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一
数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。
脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这
个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操
作可能是不正确的。
丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第
二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修。 例如:事务1读取某表中的数据A=20,事务2也读
取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第
一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的
数据是不一样的情况,因此称为不可重复读。
幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据
时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
不可重复读和幻读区别:
不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录
增多或减少了
继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类
被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让
变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要
手段
封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问
只能通过已定义的接口
多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。
可以储存和操作字符串。
其中 String 是只读字符串,也就意味着 String 引用的字符串内容是不能被改变的。
而 StringBuffer/StringBuilder 类表示的字符串对象可以直接进行修改。
List、Set 是,Map 不是。Map 是键值对映射容器,与 List 和 Set 有明显的区别, 而 Set 存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。
Collection 是一个接口,它是 Set、List 等容器的父接口;Collections 是个一个
工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、
排序、线程安全化等等。
List 以特定索引来存取元素,可以有重复元素。Set 不能存放重复元素(用对象的
equals()方法来区分元素是否重复)。Map 保存键值对(key-value pair)映射,
映射关系可以是一对一或多对一。Set 和 Map 容器都有基于哈希存储和排序树的
两种实现版本,基于哈希存储的版本理论存取时间复杂度为 O(1),而基于排序树
版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达
到排序和去重的效果
wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用
此方法要处理 InterruptedException 异常;
notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并
不能确切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且
与优先级无关;
notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给
所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;
线程池顾名思义就是事先创建若干个可执行的
线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完
毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销
newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只
有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线
程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执
行顺序按照任务的提交顺序执行。
newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创
建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就
会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小
超过了处理任务所需要的线程,那么就会回收部分空闲(60 秒不执行任务)的
线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程
池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说 JVM)
能够创建的最大线程大小。
newScheduledThreadPool:创建一个大小无限的线程池。此线程池支
持定时以及周期性执行任务的需求。
newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持
定时以及周期性执行任务的需求。
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流
化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。
序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会
存在数据乱序的问题)。
要实现序列化,需要让一个类实现 Serializable 接口
字节流和字符流。字节流继承于 InputStream、OutputStream,字符流继承于
Reader、Writer。
下面的代码以连接本机的 Oracle 数据库为例,演示 JDBC 操作数据库的步骤
加载驱动。
Class.forName("oracle.jdbc.driver.OracleDriver");
创建连接。
Connection con =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl",
"scott", "tiger");
创建语句。
PreparedStatement ps = con.prepareStatement("select * from emp
where sal between ? and ?");
ps.setInt(1, 1000);
ps.setInt(2, 3000);
执行语句。
ResultSet rs = ps.executeQuery();
处理结果。
while(rs.next()) {
System.out.println(rs.getInt("empno") + " - " +
rs.getString("ename"));
}
关闭资源。
finally {
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
} } }
方法 1:类型.class,例如:String.class
方法 2:对象.getClass(),例如:hello.getClass()
方法 3:Class.forName(),例如:Class.forName(“java.lang.String”)
饿汉式单例
public class Singleton {
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
} }
懒汉式单例
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance(){
if (instance == null) instance = new Singleton();
return instance;
} }
实现一个单例有两点注意事项,
①将构造器私有,不允许外界通过构造器创建对象;
②通过公开的静态方法向外界返回类的唯一实例。
JRE 代表 Java 运行时(Java run-time),是运行 Java 引用所必须的。JDK 代 表 Java 开发工具(Java development kit),是 Java 程序的开发工具,如 Java
编译器,它也包含 JRE。JVM 代表 Java 虚拟机(Java virtual machine),它
的责任是运行 Java 应用。JIT 代表即时编译(Just In Time compilation),当
代码执行的次数超过一定的阈值时,会将 Java 字节码转换为本地代码,如,主
要的热点代码会被准换为本地代码,这样有利大幅度提高 Java 应用的性能。
如果 a 和 b 都是对象,则 a==b 是比较两个对象的引用,只有当 a 和 b 指
向的是堆中的同一个对象才会返回 true,而 a.equals(b) 是进行逻辑比较,所以
通常需要重写该方法来提供逻辑一致性的比较。例如,String 类重写 equals() 方
法,所以可以用于两个不同对象,但是包含的字母相同的比较。
最明显的区别是 ArrrayList 底层的数据结构是数组,支持随机访问,而
LinkedList 的底层数据结构书链表,不支持随机访问。使用下标访问一个元素,
ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。
控制反转(IOC)是 Spring 框架的核心思想,用我自己的话说,就是你要做一件
事,别自己可劲 new 了,你就说你要干啥,然后外包出去就好~
依赖注入(DI) 在我浅薄的想法中,就是通过接口的引用和构造方法的表达,将
一些事情整好了反过来传给需要用到的地方~
throw 用于抛出 java.lang.Throwable 类的一个实例化对象,意思是说你可以通
过关键字 throw 抛出一个 Error 或者 一个 Exception,如:
throw new IllegalArgumentException(“size must be multiple of 2″ ) 而 throws 的作用是作为方法声明和签名的一部分,方法被抛出相应的异常以便调用者能处理。Java 中,任何未处理的受检查异常强制在 throws 子句中声明
Spring 是一个开源应用框架,旨在降低应用程序开发的复杂度。它是轻量级、松
散耦合的。它具有分层体系结构,允许用户选择组件,同时还为 J2EE 应用程序
开发提供了一个有凝聚力的框架。它可以集成其他框架,如 Structs、Hibernate、
EJB 等,所以又称为框架的框架。
由于 Spring Frameworks 的分层架构,用户可以自由选择自己需要的组件。
Spring Framework 支持 POJO(Plain Old Java Object) 编程,从而具备持续集
成和可测试性。由于依赖注入和控制反转,JDBC 得以简化。它是开源免费的。
Spring 应用一般有以下组件:
接口 - 定义功能。
Bean 类 - 它包含属性,setter 和 getter 方法,函数等。
Spring 面向切面编程(AOP) - 提供面向切面编程的功能。
Bean 配置文件 - 包含类的信息以及如何配置它们。
用户程序 - 它使用接口。
Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它
们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的
组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指
令。该元数据可以通过 XML,Java 注解或 Java 代码提供
在依赖注入中,您不必创建对象,但必须描述如何创建它们。您不是直接在代码
中将组件和服务连接在一起,而是描述配置文件中哪些组件需要哪些服务。由 IoC
容器将它们装配在一起。
IoC 的一些好处是:
它将最小化应用程序中的代码量。
它将使您的应用程序易于测试,因为它不需要单元测试用例中的任何单例或 JNDI 查找机制。
它以最小的影响和最少的侵入机制促进松耦合。
它支持即时的实例化和延迟加载服务。
它们是构成用户应用程序主干的对象。
Bean 由 Spring IoC 容器管理。
它们由 Spring IoC 容器实例化,配置,装配和管理。
Bean 是基于用户提供给容器的配置元数据创建。
基于 xml 配置
bean 所需的依赖项和服务在 XML 格式的配置文件中指定。这些配置文件通常
包含许多 bean 定义和特定于应用程序的配置选项。它们通常以 bean 标签开
头。例如:
基于注解配置
您可以通过在相关的类,方法或字段声明上使用注解,将 bean 配置为组件类本
身,而不是使用 XML 来描述 bean 装配。默认情况下,Spring 容器中未打开
注解装配。因此,您需要在使用它之前在 Spring 配置文件中启用它。例如:
基于 Java API 配置
Spring 的 Java 配置是通过使用 @Bean 和 @Configuration 来实现。
1、 @Bean 注解扮演与 元素相同的角色。
2、 @Configuration 类允许通过简单地调用同一个类中的其他 @Bean 方法
来定义 bean 间依赖关系。
例如:
@Configuration
public class StudentConfig {
@Bean
public StudentBean myStudent() {
return new StudentBean();
} }
spring bean 容器的生命周期流程如下:
1、Spring 容器根据配置中的 bean 定义中实例化 bean。
2、Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。
3、如果 bean 实现BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用setBeanName()。
4、如果 bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 setBeanFactory()。
5、如果存在与 bean 关联的任何BeanPostProcessors,则调用 preProcessBeforeInitialization() 方法。
6、如果为 bean 指定了 init 方法( 的 init-method 属性),那么将调用它。
7、最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法。
8、如果 bean 实现DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。
9、如果为bean 指定了 destroy 方法( 的 destroy-method 属性),那么将调用它。
当 bean 在 Spring 容器中组合在一起时,它被称为装配或 bean 装配。Spring
容器需要知道需要什么 bean 以及容器应该如何使用依赖注入来将 bean 绑定
在一起,同时装配 bean。
@Component :这将 java 类标记为 bean。它是任何 Spring 管理组件的通
用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。
@Controller :这将一个类标记为 Spring Web MVC 控制器。标有它的Bean 会自动导入到 IoC 容器中。
@Service :此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用
@Service 而不是 @Component,因为它以更好的方式指定了意图。
@Repository :这个注解是具有类似用途和功能的 @Component 注解的特
化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查
的异常有资格转换为 Spring DataAccessException。
@Autowired 可以更准确地控制应该在何处以及如何进行自动装配。此注解用于
在 setter 方法,构造函数,具有任意名称或多个参数的属性或方法上自动装配
bean。默认情况下,它是类型驱动的注入。
@RequestMapping 注解用于将特定 HTTP 请求方法映射到将处理相应请求的
控制器中的特定类/方法。此注释可应用于两个级别:
类级别:映射请求的 URL
方法级别:映射 URL 以及 HTTP 请求方法
1、 程序化事务管理:在此过程中,在编程的帮助下管理事务。它为您提供极大
的灵活性,但维护起来非常困难。
2、 声明式事务管理:在此,事务管理与业务代码分离。仅使用注解或基于 XML
的配置来管理事务。
AOP(Aspect-Oriented Programming), 即 面向切面编程, 它与
OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与
OOP 不同的抽象软件结构的视角. 在 OOP 中, 我们以类(class)作为我们的基
本单元, 而 AOP 中的基本单元是 Aspect(切面)
aspect 由 pointcount 和 advice 组成, 它既包含了横切逻辑的定义, 也包
括了连接点的定义. Spring AOP 就是负责实施切面的框架, 它将切面所定义的横
切逻辑编织到切面所指定的连接点中. AOP 的工作重心在于如何将增强编织目标
对象的连接点上这里包含两个工作:
1、如何通过 pointcut 和 advice 定位到特定的 joinpoint 上
2、如何在advice 中编写切面代码.
可以简单地认为, 使用 @Aspect 注解的类就是切面.
程序运行中的一些时间点, 例如一个方法的执行, 或者是一个异常的处理. 在 Spring AOP 中, join point 总是方法的执行点。
特定 JoinPoint 处的 Aspect 所采取的动作称为 Advice。Spring AOP 使用一
个 Advice 作为拦截器,在 JoinPoint “周围”维护一系列的拦截器。
实现 AOP 的技术,主要分为两大类:
静态代理
指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,
因此也称为编译时增强;
编译时编织(特殊编译器实现)
类加载时编织(特殊的类加载器实现)。
动态代理
在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
JDK 动态代理
CGLIB
将 Advice 应用于目标对象后创建的对象称为代理。在客户端对象的情况下,目
标对象和代理对象是相同的
Spring Web MVC 框架提供 模型-视图-控制器 架构和随时可用的组件,用于开
发灵活且松散耦合的 Web 应用程序。MVC 模式有助于分离应用程序的不同方
面,如输入逻辑,业务逻辑和 UI 逻辑,同时在所有这些元素之间提供松散耦合
DispatcherServlet 的工作流程可以用一幅图来说明:
1、向服务器发送 HTTP 请求,请求被前端控制器 DispatcherServlet 捕获。
2、 DispatcherServlet 根据 -servlet.xml 中的配置对请求的 URL 进行解
析,得到请求资源标识符(URI)。然后根据该 URI,调用 HandlerMapping
获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及 Handler 对
象对应的拦截器),最后以 HandlerExecutionChain 对象的形式返回。
3、 DispatcherServlet 根据获得的 Handler,选择一个合适的
HandlerAdapter。(附注:如果成功获得 HandlerAdapter 后,此时将开始
执行拦截器的 preHandler(…)方法)。
4、提取 Request 中的模型数据,填充 Handler 入参,开始执行 Handler
( Controller)。在填充 Handler 的入参过程中,根据你的配置,Spring 将
帮你做一些额外的工作:
HttpMessageConveter:将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的响应信息。
数据转换:对请求消息进行数据转换。如 String 转换成 Integer、Double 等。
数据根式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。
数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult 或 Error 中。
5、Handler(Controller)执行完成后,向 DispatcherServlet 返回一个ModelAndView 对象;
6、根据返回的 ModelAndView,选择一个适合的 ViewResolver(必须是已
经注册到 Spring 容器中的 ViewResolver)返回给 DispatcherServlet。
7、 ViewResolver 结合 Model 和 View,来渲染视图。
8、视图负责将渲染结果返回给客户端。
Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对
象,并且管理这些对象的整个生命周期。
IOC 或 依赖注入把应用的代码量降到最低。它使应用容易测试,单元测试不再需
要单例和 JNDI 查找机制。最小的代价和最小的侵入性使松散耦合得以实现。IOC
容器支持加载服务时的饿汉式初始化和懒加载。
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现
的,该类有一系列参数,每个参数代表一个对其他类的依赖。
Setter 方法注入:Setter 方法注入是容器通过调用无参构造器或无参
static 工厂 方法实例化 bean 之后,调用该 bean 的 setter 方法,即实现了基
于 setter 的依赖注入。
Spring 框架支持以下五种 bean 的作用域:
singleton : bean 在每个 Spring ioc 容器中只有一个实例。
prototype:一个 bean 的定义可以有多个实例。
request:每次 http 请求都会创建一个 bean,该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。
session:在一个 HTTP Session 中,一个 bean 定义对应一个实例。该
作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。
global-session:在一个全局的 HTTP Session 中,一个 bean 定义对应
一个实例。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。
缺省的 Spring bean 的作用域是 Singleton
Spring 容器 从 XML 文件中读取 bean 的定义,并实例化 bean。
Spring 根据 bean 的定义填充所有的属性。
如果 bean 实现了 BeanNameAware 接口,Spring 传递 bean 的 ID 到setBeanName 方法。
如果 Bean 实现了 BeanFactoryAware 接口, Spring 传递beanfactory 给 setBeanFactory 方法。
如果有任何与 bean 相关联的 BeanPostProcessors,Spring 会在postProcesserBeforeInitialization()方法内调用它们。
如果 bean 实现 IntializingBean 了,调用它的 afterPropertySet 方法,如果 bean 声明了初始化方法,调用此初始化方法。
如果有 BeanPostProcessors 和 bean 关联,这些 bean 的postProcessAfterInitialization() 方法将被调用。
如果 bean 实现了 DisposableBean,它将调用 destroy()方法。
Spring Boot 的优点有:
1、减少开发,测试时间和努力。
2、使用 JavaConfig 有助于避免使用 XML。 3、避免大量的 Maven 导入和各种版本冲突。
4、提供意见发展方法。
5、通过提供默认值快速开始开发。
6、没有单独的 Web 服务器需要。这意味着你不再需要启动 Tomcat,Glassfish或其他任何东西。
7、需要更少的配置 因为没有 web.xml 文件。只需添加用@ Configuration 注释
的类,然后添加用@Bean 注释的方法,Spring 将自动加载对象并像以前一样对其
进行管理。您甚至可以将@Autowired 添加到 bean 方法中,以使 Spring 自动装
入需要的依赖关系中。
8、基于环境的配置 使用这些属性,您可以将您正在使用的环境传递到应用程序:
-Dspring.profiles.active = {enviornment}。在加载主应用程序属性文件后,
Spring 将在(application{environment} .properties)中加载后续的应用程序属
性文件。
Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序,
提供与外部系统的集成。Spring cloud Task,一个生命周期短暂的微服务框架,
用于快速构建执行有限数据处理的应用程序。
使用 Spring Boot 开发分布式微服务时,我们面临以下问题
1、与分布式系统相关的复杂性-这种开销包括网络问题,延迟开销,带宽问题,安全问题。
2、服务发现-服务发现工具管理群集中的流程和服务如何查找和互相交谈。它涉
及一个服务目录,在该目录中注册服务,然后能够查找并连接到该目录中的服务。
3、冗余-分布式系统中的冗余问题。
4、负载平衡 --负载平衡改善跨多个计算资源的工作负荷,诸如计算机,计算机
集群,网络链路,中央处理单元,或磁盘驱动器的分布。
5、性能-问题 由于各种运营开销导致的性能问题。
6、部署复杂性-Devops 技能的要求。
在计算中,负载平衡可以改善跨计算机,计算机集群,网络链接,中央处理单元
或磁盘驱动器等多种计算资源的工作负载分布。负载平衡旨在优化资源使用,最
大化吞吐量,最小化响应时间并避免任何单一资源的过载。使用多个组件进行负
载平衡而不是单个组件可能会通过冗余来提高可靠性和可用性。负载平衡通常涉
及专用软件或硬件,例如多层交换机或域名系统服务器进程
Hystrix 是一个延迟和容错库,旨在隔离远程系统,服务和第三方库的访问点,当
出现故障是不可避免的故障时,停止级联故障并在复杂的分布式系统中实现弹性。
通常对于使用微服务架构开发的系统,涉及到许多微服务。这些微服务彼此协作。
== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,
equals用来比较的是两个对象的内容是否相等,
i++:先赋值,后计算
++i:先计算,后赋值
方法的重载就是在同一个类中允许同时存在一个以上的同名方法,只要它们的参数个数或者类型不同即可。在这种情况下,该方法就叫被重
载了,这个过程称为方法的重载(override)
charAt:返回指定索引处的字符
indexOf():返回指定字符的索引
replace():字符串替换
trim():去除字符串两端空白
split():分割字符串,返回一个分割后的字符串数组
getBytes():返回字符串的byte类型数组
length():返回字符串长度
toLowerCase():将字符串转成小写字母
toUpperCase():将字符串转成大写字符
substring():截取字符串
format():格式化字符串
equals():字符串比较
Super表示当前类的父类对象
This表示当前类的对象
抽象类:
加载数据库驱动类
打开数据库连接
执行sql语句
处理返回结果
关闭资源
类是对象的抽象,对象是类的具体,类是对象的模板,对象是类的实例