Java后端面试题攻略查漏补缺(三)

1 简述InnoDB和Myisam的区别

1.Myisam是默认表类型不是事务安全的;InnoDB支持事务。

2.Myisam不支持外键;Innodb支持外键。

3.Myisam支持表级锁(不支持高并发,以读为主);InnoDB支持行锁(共享锁,排它锁,意向锁),粒度更小,但是在执行不能确定扫描范围的sql语句时,InnoDB同样会锁全表。

4.执行大量select,Myisam是最好的选择;执行大量的update和insert最好用InnoDB。

5.Myisam在磁盘上存储上有三个文件.frm(存储表定义) .myd(存储表数据) .myi(存储表索引);innodb磁盘上存储的是表空间数据文件和日志文件,InnoDB表大小只受限于操作系统大小。

6.Myisam使用非聚集索引,索引和数据分开,只缓存索引;InnoDB使用聚集索引,索引和数据存在一个文件。

7.Myisam保存表具体行数;InnoDB不保存。

8.delete from table时,Myisam会重新建表,而InnoDB会一行一行的删除。

2 MySQL索引类型有哪些?以及对数据库的性能的影响?

1)普通索引:允许被索引的数据列包含重复的值。
2)唯一索引:可以保证数据记录的唯一性。
3)主键索引:是一种特殊的唯一索引,在一张表中只能定义一个主键索引,主键用于唯一标识一条记录,使用关键字 PRIMARY KEY 来创建。
4)联合索引:索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引。
5)全文索引:通过建立倒排索引,可以极大的提升检索效率,解决判断字段是否包含的问题,是目前搜索引擎使用的一种关键技术。可以通过ALTER TABLE table_name ADD FULLTEXT (column);创建全文索引

索引可以极大的提高数据的查询速度。通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
但是会降低插入、删除、更新表的速度,因为在执行这些写操作时,还要操作索引文件

索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大,如果非聚集索引很多,一旦聚集索引改变,那么所有非聚集索引都会跟着变。

3 Spring的bean生命周期?

img

1)实例化Bean

对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。
对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。
容器通过获取BeanDefinition对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。
实例化对象被包装在BeanWrapper对象中,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制设置属性。

2)设置对象属性(依赖注入)

实例化后的对象被封装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入。
紧接着,Spring根据BeanDefinition中的信息进行依赖注入。
并且通过BeanWrapper提供的设置属性的接口完成依赖注入。

3)注入Aware接口

Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean。

4)BeanPostProcessor(前置处理和后置处理)

当经过上述几个步骤后,bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现。
该接口提供了两个函数:

  • postProcessBeforeInitialzation( Object bean, String beanName )
    当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。
    这个函数会先于InitialzationBean执行,因此称为前置处理。
    所有Aware接口的注入就是在这一步完成的。
  • postProcessAfterInitialzation( Object bean, String beanName )
    当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。
    这个函数会在InitialzationBean完成后执行,因此称为后置处理。

5) InitializingBean与init-method

当BeanPostProcessor的前置处理完成后就会进入本阶段。
InitializingBean接口只有一个函数:

  • afterPropertiesSet()

这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。
若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。

当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口。

6)DisposableBean和destroy-method

和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑。

4 怎么处理MySQL的慢查询?

1、开启慢查询日志,准确定位到哪个sql语句出现了问题

2、分析sql语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写

3、分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引

4、如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。

优化语句:

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。

5 如何理解Springboot中的Starter?

starter就是定义⼀个starter的jar包,写⼀个@Configuration配置类、将这些bean定义在⾥⾯,然后在starter包的META-INF/spring.factories中写⼊该配置类,springboot会按照约定来加载该配置类开发⼈员只需要将相应的starter包依赖进应⽤,进⾏相应的属性配置(使⽤默认配置时,不需要配置),就可以直接进⾏代码开发,使⽤对应的功能了。

⽐如mybatis-spring-boot-starter,spring-boot-starter-redis,我们自己写一个starter自动配置启动,写一个我们自己的线程池,用@Configuration+@Bean定义一个线程池,将这个配置类的路径写到spring.factories中,就可以了,打上jar包,在其他地方引用,用@Autowired自动注入我们的Bean使用就可以。

6 如何实现一个IOC容器?

IOC(Inversion of Control),意思是控制反转,不是什么技术,而是一种设计思想,IOC意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

在传统的程序设计中,我们直接在对象内部通过new进行对象创建,是程序主动去创建依赖对象,而IOC是有专门的容器来进行对象的创建,即IOC容器来控制对象的创建。

在传统的应用程序中,我们是在对象中主动控制去直接获取依赖对象,这个是正转,反转是由容器来帮忙创建及注入依赖对象,在这个过程过程中,由容器帮我们查找级注入依赖对象,对象只是被动的接受依赖对象。

  1. 先准备一个基本的容器对象,包含一些map结构的集合,用来方便后续过程中存储具体的对象
  2. 进行配置文件的读取工作或者注解的解析工作,将需要创建的bean对象都封装成BeanDefinition对象存储在容器中
  3. 容器将封装好的BeanDefinition对象通过反射的方式进行实例化,完成对象的实例化工作
  4. 进行对象的初始化操作,也就是给类中的对应属性值就行设置,也就是进行依赖注入,完成整个对象的创建,变成一个完整的bean对象,存储在容器的某个map结构中
  5. 通过容器对象来获取对象,进行对象的获取和逻辑处理工作
  6. 提供销毁操作,当对象不用或者容器关闭的时候,将无用的对象进行销毁

7 SpringCloud核心组件有哪些?分别有什么作用?

1)服务发现——Netflix Eurek

该系统下还分为Eureka服务端和Eureka客户端,Eureka服务端用作服务注册中心,支持集群部署。Eureka客户端是一个java客户端,用来处理服务注册与发现。

2)客服端负载均衡——Netflix Ribbon

基于Http和Tcp的客户端负载均衡,使得面向REST请求时变换为客户端的负载服务调用,提供客户端的软件负载均衡算法。

3)断路器——Netflix Hystrix

它的作用是保护系统,控制故障范围。

4)服务网关——Netflix Zuul

提供api网关,路由,负载均衡等作用

5)分布式配置——Spring Cloud Config

提供服务端和客户端,服务器存储后端的默认实现使用git

8 讲一下对AOP的理解

AOP全称叫做 Aspect Oriented Programming 面向切面编程。它是为解耦而生的,解耦是程序员编码开发过程中一直追求的境界,AOP在业务类的隔离上,绝对是做到了解耦,在这里面有几个核心的概念:

  • 切面(Aspect): 指关注点模块化,这个关注点可能会横切多个对象。事务管理是企业级Java应用中有关横切关注点的例子。 在Spring AOP中,切面可以使用通用类基于模式的方式(schemabasedapproach)或者在普通类中以 @Aspect 注解(@AspectJ 注解方式)来实现。
  • 连接点(Join point): 在程序执行过程中某个特定的点,例如某个方法调用的时间点或者处理异常的时间点。在Spring AOP中,一个连接点总是代表一个方法的执行。
  • 通知(Advice): 在切面的某个特定的连接点上执行的动作。通知有多种类型,包括“around”,“before” and “after”等等。 许多AOP框架,包括Spring在内,都是以拦截器做通知模型的,并维护着一个以连接点为中心的拦截器链。
  • 切点(Pointcut): 匹配连接点的断言。通知和切点表达式相关联,并在满足这个切点的连接点上运行(例如,当执行某个特定名称的方法时)。切点表达式如何和连接点匹配是AOP的核心:Spring默认使用AspectJ切点语义。
  • 引入(Introduction): 声明额外的方法或者某个类型的字段。Spring允许引入新的接口(以及一个对应的实现)到任何被通知的对象上。例如,可以使用引入来使bean实现 IsModified 接口, 以便简化缓存机制(在AspectJ社区,引入也被称为内部类型声明(inter))。
  • 目标对象(Target object): 被一个或者多个切面所通知的对象。也被称作被通知(advised)对象。既然Spring AOP是通过运行时代理实现的,那么这个对象永远是一个被代理(proxied)的对象。
  • AOP代理(AOP proxy):AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)。在Spring中,AOP代理可以是JDK动态代理或CGLIB代理。
  • 织入(Weaving): 把切面连接到其它的应用程序类型或者对象上,并创建一个被被通知的对象的过程。这个过程可以在编译时(例如使用AspectJ编译器)、类加载时或运行时中完成。 Spring和其他纯Java AOP框架一样,是在运行时完成织入的。

任何一个系统都是由不同的组件组成的,每个组件负责一块特定的功能,当然会存在很多组件是跟业务无关的,例如日志、事务、权限等核心服务组件,这些核心服务组件经常融入到具体的业务逻辑中,如果我们为每一个具体业务逻辑操作都添加这样的代码,很明显代码冗余太多,因此我们需要将这些公共的代码逻辑抽象出来变成一个切面,然后注入到目标对象(具体业务)中去,AOP正是基于这样的一个思路实现的,通过动态代理的方式,将需要注入切面的对象进行代理,在进行调用的时候,将公共的逻辑直接添加进去,而不需要修改原有业务的逻辑代码,只需要在原来的业务逻辑基础之上做一些增强功能即可。

9 讲一下对IOC的理解

IOC容器:实际上就是map,里面存的是各种对象(在XML里配置的bean节点,@respository,@service,@controller,@component),在项目启动的时候会读取配置文件里面的bean节点,根据全限定类名使用反射创建对象放到map里,扫描到打上上述注解的类还是通过反射的方式创建对象放到map里面。

这个时候map里面就有各种对象了,接下来我们再代码里面需要用到里面的对象时,再通过DI注入(@Autowired,@Resources,@Qualifier等注解),xml里bean 节点内的ref属性,项目启动时读取xml节点ref属性根据id注入,也会扫描到这些注解,根据类型或者id注入,id就是对象名。

  • 控制反转:

没有引入IOC容器之前,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须去主动创建对象B或者使用已经创建的对象B,无论是创建还是使用对象B,控制权都在A类。

引入IOC容器后,对象A和对象B之间失去了直接联系,当对象A运行到需要对象B的时候,IOC容器会主动创建对象B注入到对象A所需要的地方。

通过前后对比,不难看出:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是控制反转。

  • 依赖注入:

“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变成了由IOC容器自动注入。依赖注入是实现IOC的方法,就是由IOC在运行期间,动态的将某种依赖关系注入到对象之中。

10 索引的设计原则有哪些?

在进行索引设计的时候,应保证索引字段占用的空间越小越好,这只是一个大的方向,还有一些细节需要注意:

1、适合索引的列是出现在where子句中的列,或者链接子句中的列。

2、基数较小的表,索引效果差,没必要创建索引。

3、在选择索引列的时候,越短越好,可以指定某些列的一部分不,没必要用全部字段的值。

4、不要给表的没有给字段都创建索引,并不是索引越多越好。

5、定义有外键的数据列一定药创建索引。

6、更新频繁的字段不要有索引。

7、创建索引的列不要过多,可以创建组合索引,但是组合索引的列的个数不建议太多。

8、大文本,大对象不要创建索引。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值