简单面试题分享

分享一些简单的面试题目解答

今天是1024了,留个纪念放一些以前面试过的题目,初学者可以简单看一看。

学习使人进步,通过面试题了解公司使用技术

1.停电了redis数据还在吗 在
redis虽然是基于内存存贮,但提供了两种持久化的方式,一种是rdb,可以设置,例如 1秒内数据更新100次,生成一个rdb文件,进行全量的数据快照操作。
优点就是服务重启后,加载文件恢复数据比较快,缺点就是在时间间隔内服务挂了,会丢数据。
另一种是aof,就是将每次对数据更改的redis命令写到aof文件中,
优点就是数据基本不会丢失,即使丢失也是很少量,缺点就是服务器重启后,要加载aof文件,执行aof文件中存储的redis命令,如果文件很大,执行时间比较慢,而且redis不能接受请求。

在主从备份时瞬间机器故障理论上是会出现数据丢失的,毕竟是tcp长连接,做过长连接的都知道服务发现连接断开一般也得通过心跳包,而心跳包是需要间隔时间的,主从选举也得在这个或者几个心跳间隔时间之后才会进行。命令备份和定点存数据是redis保证数据一致性的一种手段,也不是尽善尽美,而且有时我们为了尽可能的挖掘redis性能,一般也会把redis的命令备份或定点存数据功能关闭。
作为缓存中间层,偶尔的数据丢失是没问题的,只要保证数据能正常落地数据库,缓存丢失最多就是缓存穿透直达数据库而已。

在主从备份时瞬间机器故障理论上是会出现数据丢失的,毕竟是tcp长连接,做过长连接的都知道服务发现连接断开一般也得通过心跳包,而心跳包是需要间隔时间的,主从选举也得在这个或者几个心跳间隔时间之后才会进行。命令备份和定点存数据是redis保证数据一致性的一种手段,也不是尽善尽美,而且有时我们为了尽可能的挖掘redis性能,一般也会把redis的命令备份或定点存数据功能关闭。
作为缓存中间层,偶尔的数据丢失是没问题的,只要保证数据能正常落地数据库,缓存丢失最多就是缓存穿透直达数据库而已。
2.redis和MongoDB的区别
内存管理机制上:Redis 数据全部存在内存,定期写入磁盘,当内存不够时,可以选择指定的 LRU 算法删除数据。
				MongoDB 数据存在内存,由 linux系统 mmap 实现,当内存不够时,只将热点数据放入内存,其他数据存在磁盘。
支持的数据结构上:Redis 支持的数据结构丰富,包括hash、set、list等。
				  MongoDB 数据结构比较单一,但是支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富

Redis和MongoDB的区别(面试受用)
项目中用的是MongoDB,但是为什么用其实当时选型的时候也没有太多考虑,只是认为数据量比较大,所以采用MongoDB。
之前也用过redis,当时是用来存储一些热数据,量也不大,但是操作很频繁。现在项目中用的是MongoDB,目前是百万级的数据,将来会有千万级、亿级。

就Redis和MongoDB来说,大家一般称之为Redis缓存、MongoDB数据库。这也是有道有理有根据的,
Redis主要把数据存储在内存中,其“缓存”的性质远大于其“数据存储“的性质,其中数据的增删改查也只是像变量操作一样简单;
MongoDB却是一个“存储数据”的系统,增删改查可以添加很多条件,就像SQL数据库一样灵活,这一点在面试的时候很受用。

Mongodb与Redis应用指标对比
MongoDB和Redis都是NoSQL,采用结构型数据存储。二者在使用场景中,存在一定的区别,这也主要由于
二者在内存映射的处理过程,持久化的处理方法不同。MongoDB建议集群部署,更多的考虑到集群方案,Redis
更偏重于进程顺序写入,虽然支持集群,也仅限于主-从模式。
3.equals和==
    ==是直接比较的两个对象的堆内存地址,如果相等,则说明这两个引用实际是指向同一个对象地址的。
    对于基本数据类型(byte,short,char,int,float,double,long,boolean)来说,他们是作为常量在方法区中的常量池里面以HashSet策略存储起来的,
对于这样的字符串 "123"?也是相同的道理,在常量池中,一个常量只会对应一个地址,
因此不管是再多的 123,"123" 这样的数据都只会存储一个地址,所以所有他们的引用都是指向的同一块地址,因此基本数据类型和String常量是可以直接通过==来直接比较的。
    另外,对于基本数据的包装类型(Byte, Short, Character,Integer,Float, Double,Long, ?Boolean)除了Float和Double之外,其他的六种都是实现了常量池的,
因此对于这些数据类型而言,一般我们也可以直接通过==来判断是否相等
Integer a = 15; Integer b = 15; System.out.printle(a == b);  -- true
Integer c = 127; Integer d = 128; System.out.printle(c == d); -- false
因为 Integer 在常量池中的存储范围为[-128,127],127在这范围内,因此是直接存储于常量池的,而128不在这范围内,
所以会在堆内存中创建一个新的对象来保存这个值,所以m,n分别指向了两个不同的对象地址,故而导致了不相等。

equals首先判断的是对象的地址是否相同,相等就继续进行判断成员变量是否相同。
equals在Object类型的equals方法是直接通过==来比较的,和==是没有任何区别的。
Java提供的所有类中,绝大多数类都重写了equals()方法,重写后的equals()方法一般都是比较两个对象的值
4.成员变量和局部变量的区别:
(1)在类中的位置不同
成员变量:类中方法外
局部变量:方法定义中或者方法声明上
(2)在内存中的位置不同
成员变量:在堆中
局部变量:在栈中
(3)生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
(4)初始化值不同
成员变量:有默认值
局部变量:没有默认值,必须定义,赋值,然后才能使用
5.java的特性
抽象:就是把现实生活中的某一类东西提取出来,用程序代码表示,我们通常叫做类或者接口。
	  抽象包括两个方面:一个是数据抽象,一个是过程抽象。数据抽象也就是对象的属性。过程抽象是对象的行为特征。
封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行封装隐藏。封装分为属性的封装和方法的 封装。
继承:是对有着共同特性的多类事物,进行再抽象成一个类。这个类就是多类事物的父类。父类的意义在于抽取多类事物的共性。
多态:允许不同类的对象对同一消息做出响应。方法的重载、类的覆盖正体现了多态。
6.什么是面向对象?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面 
	1.面向切面编程提供声明式事务管理 
	2.spring支持用户自定义的切面 
aop框架具有的两个特征: 
	1.各个步骤之间的良好隔离性 
	2.源代码无关性 
7.抽象和接口的区别
1)接口可以多实现,抽象类只能单继承。
2)接口里的成员变量,不能更改的,因为修饰符是:public static final;方法默认public abstract修饰的
相同点:
	都无法实例对象
	可以定义无方法体的方法
不同点:
	抽象类是一种类只能单继承,接口可以多实现
	抽象类中 可以有普通方法,接口在jdk1.8之前是不可以定义普通方法的
	抽象类中可以有普通变量 接口中的变量都是由final修饰的
	抽象类可以有构造器和主方法(抽象类中的构造器主要是在子类的构造方法中调用,负责初始化抽象类中的参数),接口中不可以有构造器和主方法
	抽象类中的方法普通可以由public,private? ?protected 和默认修饰? ?抽象方法可以由 public protected(或者不加修饰符)修饰? 抽象方法必须由abstract修饰????接口方法默认由public修饰 接口中的抽象方法只能由public修饰? default在接口中只能修饰带有方法体的方法?
使用场景:
	当需要一些默认的方法实现时需要使用抽象类
	当需要多继承时使用接口
	当需要不断增加基础功能的时候使用抽象类? 当使用接口时 增加功能就需要修改每个实现了该接口的实现类
1 接口是核心,其定义了要做的事情,包含了许多的方法,但没有定义这些方法应该如何做。
2 如果许多类实现了某个接口,那么每个都要用代码实现那些方法
3 如果某一些类的实现有共通之处,则可以抽象出来一个抽象类,让抽象类实现接口的公用的代码,而那些个性化的方法则由各个子类去实现。
所以,抽象类是为了简化接口的实现,他不仅提供了公共方法的实现,让你可以快速开发,又允许你的类完全可以自己实现所有的方法,不会出现紧耦合的问题。
应用场合很简单了
1 优先定义接口
2 如果有多个接口实现有公用的部分,则使用抽象类,然后集成它。
8.抽象类和普通类的区别
抽象类不能被实例化
抽象类可以有抽象方法,抽象方法只需申明,无需实现
含有抽象方法的类必须申明为抽象类
抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类
抽象方法不能被声明为静态
抽象方法不能用private修饰
抽象方法不能用final修饰。
	1.抽象类不能被实例化。
	2.抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态。
	3.抽象方法只需申明,而无需实现,抽象类中可以允许普通方法有主体
	4.含有抽象方法的类必须申明为抽象类
	5.抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类。
	抽象类是否可以有构造函数?答案是可以有。抽象类的构造函数用来初始化抽象类的一些字段,而这一切都在抽象类的派生类实例化之前发生。
不仅如此,抽线类的构造函数还有一种巧妙应用:就是在其内部实现子类必须执行的代码
9.构造方法有什么用
1.构造方法作用:(1).构造出来一个类的实例 (2).对构造出来一个类的实例(对象)初始化。
2.构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有。
3.主要完成对象的初始化工作,构造方法的调用是在创建一个对象时使用new操作进行的。
4.类中必定有构造方法,若不写,系统自动添加无参构造方法。接口不允许被实例化,所以接口中没有构造方法。
5.不能被static、final、synchronized、abstract和native修饰。
6.构造方法在初始化对象时自动执行,一般不能显式地直接调用.当同一个类存在多个构造方法时,java编译系统会自动按照初始化时最后面括号的参数个数以及参数类型来自动一一对应。完成构造函数的调用。
7.构造方法分为两种:无参构造方法 有参构造方法
构造方法可以被重载。没有参数的构造方法称为默认构造方法,与一般的方法一样,构造方法可以进行任何活动,但是经常将他设计为进行各种初始化活动,比如初始化对象的属性。
10.static
用法:是一个修饰符;用于修饰成员(成员变量和成员函数)
当成员被静态修饰后,就多了一种调用方式抄,除了可以被对象调用外,还可以直接被类名调用格式:类名.静态成员
	1.static关键字修饰类
	2.static关键字修饰方法
	3.static关键字修饰变量
	4.static关键字修饰代码块
静态的特点:
	1.随着类的加载而加载:也就是说静态会随着类的消失而消失,说明静态的生命周期最长
	2.优先于对象的存在,明确一点:静态是先存在的对象是后存在的
	3.被所有对象共享
	4.可以直接被类名多调用
实例变量和类变量的区别
1.存放位置,类变量随着类的加载存在于方法区中,实例变量随着对象的对象的建立存在于堆内存里
2.生命周期,类变量生命周期最长,随着“类”的加载而加载,随着类的消失而消失,实例变量随着“对象”的消失而消失
11.static关键字
1、被static修饰的变量属于类变量,可以通过类名.变量名直接引用,而不需要new出一个类来
2、被static修饰的方法属于类方法,可以通过类名.方法名直接引用,而不需要new出一个类来
	被static修饰的变量、被static修饰的方法统一属于类的静态资源,是类实例之间共享的,换言之,一处变、处处变。
JDK把不同的静态资源放在了不同的类中而不把所有静态资源放在一个类里面,很多人可能想当然认为当然要这么做,但是是否想过为什么要这么做呢?个人认为主要有三个好处:
	1、不同的类有自己的静态资源,这可以实现静态资源分类。比如和数学相关的静态资源放在java.lang.Math中,和日历相关的静态资源放在java.util.Calendar中,这样就很清晰了
	2、避免重名。不同的类之间有重名的静态变量名、静态方法名也是很正常的,如果所有的都放在一起不可避免的一个问题就是名字重复,这时候怎么办?分类放置就好了。
	3、避免静态资源类无限膨胀,这很好理解。
静态资源属于类,但是是独立于类存在的。从JVM的类加载机制的角度讲,======静态资源是类初始化的时候加载的,而非静态资源是类new的时候加载的。 
类的初始化早于类的new,比如Class.forName(“xxx”)方法,就是初始化了一个类,但是并没有new它,只是加载这个类的静态资源罢 了。
所以对于静态资源来说,它是不可能知道一个类中有哪些非静态资源的;但是对于非静态资源来说就不一样了,由于它是new出来之后产生的,因此属于类的 这些东西它都能认识。
所以上面的几个问题答案就很明确了:
	1、静态方法能不能引用非静态资源?不能,new的时候才会产生的东西,对于初始化后就存在的静态资源来说,根本不认识它。
	2、静态方法里面能不能引用静态资源?可以,因为都是类初始化的时候加载的,大家相互都认识。
	3、非静态方法里面能不能引用静态资源?可以,非静态方法就是实例方法,那是new之后才产生的,那么属于类的内容它都认识。
静态块
静态块也是static的重要应用之一。也是用于初始化一个类的时候做操作用的,和静态变量、静态方法一样,静态块里面的代码只执行一次,且只在初始化类的时候执行。
12.string,stringBuffer,stringBuilder的区别
(1)String是内容不可变的,而StringBuffer、StringBuilder都是内容可变的。
(2)StringBuffer是同步的,数据安全的,但是效率低;   
	 StringBuilder是不同步的,数据不安全,相比于来说,效率高。
(1)如果要操作少量的数据用 String;
(2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;
(3)单线程操作字符串缓冲区下操作大量数据 StringBuilder。
13.#{}和${}的区别
#{}是一个占位符;
#{}可以防止SQL注入,提高系统安全性
#{}可以自动进行Java类型和jdbc类型的转换;
#{}里面如果是字符类型或者是简单类型,可以写任意值;
#{}里面如果是对象类型,解析符合OGNL表达式规则;
${}是原封不动SQL拼接;
${}里面是字符类型或简单类型,只能写value;
${}里面如果是对象类型,解析符合OGNL表达式规则;
${}无法防止SQL注入;
14.sql中的分页实现
1.两种方式
  1.1:row_number() over()函数
		SELECT TOP 页大小 *
		   FROM( SELECT ROW_NUMBER() OVER (ORDER BY id) AS RowNumber,* FROM table1 )as A 
		   WHERE RowNumber > 页大小*(页数-1)
		   --注解:首先利用Row_number()为table1表的每一行添加一个行号,给行号这一列取名'RowNumber' 在over()方法中将'RowNumber'做了升序排列
		   --然后将'RowNumber'列 与table1表的所有列 形成一个表A
		   --重点在where条件。假如当前页(currentPage)是第2页,每页显示10个数据(pageSzie)。那么第一页的数据就是第11-20条
		   --所以为了显示第二页的数据,即显示第11-20条数据,那么就让RowNumber大于 10*(2-1)
  1.2:OFFSET ....FETCH 
		OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
		指定在从查询表达式中开始返回行之前,将跳过的行数。OFFSET 子句的参数可以是大于或等于零的整数或表达式。ROW 和 ROWS 可以互换使用。
15.内连接,左连接,右连接的区别:
内连接:指主表,从表中符合连接条件的记录全部显示
左连接:外连接方式,主要是显示主表,从表中符合连接条件的记录,并且主表中所有不符合连接条件的记录也要显示。
右连接:外连接方式,主要是显示主表,从表中所有符合连接条件的记录,并且从表中不符合的记录也要显示。
16.MySQL数据库与Oracle数据库有什么区别
1)应用方面:MySQL是中小型应用的数据库,一般用于个人项目或中小型网站及论坛。Oracle属于大型数据库,一般在具有相当规模的企业应用。
2)自动增长的数据类型方面:MySQL有自动增长的数据类型。Oracle没有自动增长的数据类型,需要建立一个自增序列
3)group by用法:MySQL中group by在select语句中可以随意使用,但是在Oracle中如果查询语句中有组函数,那其他列名必须是组函数处理过的或者是groupby子句中的列,否则报错
4)引号方面:MySQL中用双引号包起字符串,Oracle中只可以用单引号包起字符串
MySQL和Oracle的区别
  由于SQL Server不常用,所以这里只针对MySQL数据库和Oracle数据库的区别
	(1) 对事务的提交
		MySQL默认是自动提交,而Oracle默认不自动提交,需要用户手动提交,需要在写commit;指令或者点击commit按钮
	(2) 分页查询
		MySQL是直接在SQL语句中写"select... from ...where...limit  x, y",有limit就可以实现分页;而Oracle则是需要用到伪列ROWNUM和嵌套查询
	(3) 事务隔离级别
		  MySQL是read commited的隔离级别,而Oracle是repeatable read的隔离级别,同时二者都支持serializable串行化事务隔离级别,可以实现最高级别的读一致性。
	(4) 对事务的支持
		MySQL在innodb存储引擎的行级锁的情况下才可支持事务,而Oracle则完全支持事务
	(5) 保存数据的持久性
		MySQL是在数据库更新或者重启,则会丢失数据,Oracle把提交的sql操作线写入了在线联机日志文件中,保持到了磁盘上,可以随时恢复
	(6) 并发性
		MySQL以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。
	    虽然InnoDB引擎的表可以用行级锁,但这个行级锁的机制依赖于表的索引,如果表没有索引,或者sql语句没有使用索引,那么仍然使用表级锁。
	    Oracle使用行级锁,对资源锁定的粒度要小很多,只是锁定sql需要的资源,并且加锁是在数据库中的数据行上,不依赖与索引。
		所以Oracle对并发性的支持要好很多。
	(7) 逻辑备份
		MySQL逻辑备份时要锁定数据,才能保证备份的数据是一致的,影响业务正常的dml使用,Oracle逻辑备份时不锁定数据,且备份的数据是一致
	(8) 复制
		MySQL:复制服务器配置简单,但主库出问题时,丛库有可能丢失一定的数据。且需要手工切换丛库到主库。
		Oracle:既有推或拉式的传统数据复制,也有dataguard的双机或多机容灾机制,主库出现问题是,可以自动切换备库到主库,但配置管理较复杂。
	(9) 性能诊断
		MySQL的诊断调优方法较少,主要有慢查询日志。
		Oracle有各种成熟的性能诊断调优工具,能实现很多自动分析、诊断功能。比如awr、addm、sqltrace、tkproof等    
	(10)权限与安全
		MySQL的用户与主机有关,感觉没有什么意义,另外更容易被仿冒主机及ip有可乘之机。
		Oracle的权限与安全概念比较传统,中规中矩。
	(11)分区表和分区索引
		MySQL的分区表还不太成熟稳定。
		Oracle的分区表和分区索引功能很成熟,可以提高用户访问db的体验。
	(12)最重要的区别
		MySQL是轻量型数据库,并且免费,没有服务恢复数据。
		Oracle是重量型数据库,收费,Oracle公司对Oracle数据库有任何服务。
17.Java中遍历Map对象的4种方法:
1、通过Map.entrySet遍历key和value,在for-each循环中使用entries来遍历.推荐,尤其是容量大时。
2、通过Map.keySet遍历key,通过键找值value遍历(效率低),普遍使用,二次取值。
3、如果只需要map中的键或者值,你可以通过Map.keySet或Map.values来实现遍历,而不是用entrySet。在for-each循环中遍历keys或values。
4、通过Map.entrySet使用iterator迭代器遍历key和value(大容量,效率高)
18.静态变量和实例变量的区别?
语法区别:静态变量需要static关键字修饰,实例变量不需要。
程序运行时的区别:静态变量从属于类,实例变量从属于对象。
  实例变量必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量;
  静态变量即类别量,只要程序加载了类的字节码,静态变量就会被分配空间,即可使用。
综上,实例变量必须创建对象后通过这个对象来使用,静态变量可以直接使用类名来引用。
19.mysql聚合函数
聚合函数是平时比较常用的一类函数,这里列举如下:
COUNT(col)   统计查询结果的行数
MIN(col)   查询指定列的最小值
MAX(col)   查询指定列的最大值
SUM(col)   求和,返回指定列的总和
AVG(col)   求平均值,返回指定列数据的平均值
20.数据库删除数据delta,数据库怎么删除drop,还有什么删除
truncate和delete区别:
1)Truncate和delete都可以将数据实体删掉,truncate操作不记录到rollback日志,同时数据不能恢复
2)Truncate是数据定义语言(DDL),delete是数据操作语言(DML)
3)Truncate不能对视图进行操作,delete操作不会腾出表空间的内存
21.list,set,map之间的区别
1、List、Set都是继承自Collection接口,Map则不是
2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,
(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,
 另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。) 
3、Set和List对比: 
	Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。 
	List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。 
4、Map适合储存键值对的数据
5、线程安全集合类与非线程安全集合类 :
	LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
	HashMap是非线程安全的,HashTable是线程安全的;
	StringBuilder是非线程安全的,StringBuffer是线程安全的。
22.依赖注入(DI)和 控制反转(IOC)是同一个概念。(setter注入,构造器注入,接口注入)
	具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。
但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入
	Person与Axe之间没有任何代码耦合关系,bean与bean之间的依赖关系由Spring管理。======采用setter方法为目标bean注入属性的方式,称为设值注入;
业务对象的更换变得相当简单,对象与对象之间的依赖关系从代码里分离出来,通过配置文件动态管理。
所谓构造注入,指通过构造函数来完成依赖关系的设定,而不是通过setter方法。
	区别在于:创建Person实例中Axe属性的时机不同=====设值注入是先创建一个默认的bean实例,然后调用对应的构造方法注入依赖关系。
而构造注入则在创建bean实例时,已经完成了依赖关系的;
	控制反转IOC是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IOC容器,
它就是一个专门用来创建对象的工厂(BeanFactory),你要什么对象,它就给你什么对象,有了 IOC容器,依赖关系就变了,原先的依赖关系就没了,
它们都依赖IOC容器了,通过IOC容器来建立它们之间的关系。
最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。

spring最基础的能力是IOC(依赖注入),AOP(面向切面编程),ioc改善了模块之间的耦合问题,
依赖注入的方式:set方法,构造方法,成员变量+ @Autowire ;Bean的管理是IOC的主要功能。
bean的生命周期完全由spring容器管理,从属性设置到各种依赖关系的注入,简化了开发人员对bean的生命周期认知;
23.什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面 
	1.面向切面编程提供声明式事务管理 
	2.spring支持用户自定义的切面 
aop框架具有的两个特征: 
	1.各个步骤之间的良好隔离性 
	2.源代码无关性 
AOP可以做什么?
1.Spring声明式事务管理配置。
2.Controller层的参数校验。
3.使用Spring AOP实现MySQL数据库读写分离案例分析
4.在执行方法前,判断是否具有权限。
5.对部分函数的调用进行日志记录。监控部分重要函数,若抛出指定的异常,可以以短信或邮件方式通知相关人员。
6.信息过滤,页面转发等等功能,
24.Spring的事务管理机制实现的原理,
	就是通过这样一个动态代理对所有需要事务管理的Bean进行加载,并根据配置在invoke方法中对当前调用的方法名进行判定,
并在method.invoke方法前后为其加上合适的事务管理代码,这样就实现了Spring式的事务管理。Spring中的AOP实 现更为复杂和灵活,不过基本原理是一致的。
25.Spring Bean的作用域
spring bean的作用域分为5种,分别是 singleton、prototype、request、session、global-session这五种
26.spring是什么?
spring是一个集成了许多第三方框架的大杂烩,其核心技术是IOC(控制反转,也称依赖注入)和AOP(面向切面编程)
它是怎样来简化开发的呢?让我们看看spring采取的关键策略。
基于POJO的轻量级和最小侵入性编程;
通过依赖注入和面向接口实现松耦合;
基于切面和惯例进行声明式编程;
通过切面和模板减少样板式代码。
27.String框架的注解
1、声明bean的注解
	@Component 组件,没有明确的角色
	@Service 在业务逻辑层使用(service层)
	@Repository 在数据访问层使用(dao层)
	@Controller 在展现层使用,控制器的声明(C)
2、注入bean的注解
	@Autowired:由Spring提供
	@Inject:由JSR-330提供
	@Resource:由JSR-250提供
3、java配置类相关注解
	@Configuration 声明当前类为配置类,相当于xml形式的Spring配置(类上)
	@Bean 注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式(方法上)
	@Configuration 声明当前类为配置类,其中内部组合了@Component注解,表明这个类是一个bean(类上)
	@ComponentScan 用于对Component进行扫描,相当于xml中的(类上)
4、切面(AOP)相关注解
	Spring支持AspectJ的注解式切面编程。
	@Aspect 声明一个切面(类上)
	使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。
	@After 在方法执行之后执行(方法上)
	@Before 在方法执行之前执行(方法上)
	@Around 在方法执行之前与之后执行(方法上)
5、@Bean的属性支持
	@Scope 设置Spring容器如何新建Bean实例(方法上,得有@Bean)
	其设置类型包括:
		Singleton (单例,一个Spring容器中只有一个bean实例,默认模式),
		Protetype (每次调用新建一个bean),
		Request (web项目中,给每个http request新建一个bean),
		Session (web项目中,给每个http session新建一个bean),
		GlobalSession(给每一个 global http session新建一个Bean实例)
6、@Value注解
	@Value 为属性注入值(属性上)
28.bean的运行周期
在说明前可以思考一下Servlet的生命周期:实例化,初始init,接收请求service,销毁destroy;
Spring上下文中的Bean也类似,如下
	1、实例化一个Bean--也就是我们常说的new;
	2、按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;
	3、如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值
	4、如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);
	5、如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);
	6、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;
	7、如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
	8、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;
	注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。
	9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
	10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值