JAVA 面试遇到的常见问题

ArrayList与LinkdList的区别?

ArrayList:基于动态数组,连续内存存储,适合下标访问(随机访问)

LinkedList:基于链表,存储在分散的内存中,适合做数据的插入,删除,不适合查询,必须使用iterator遍历

  • Spring是什么?

轻量级开源的J2EE框架;
是一个容器框架,用来装JavaBean(Java对象);
中间层框架,起一个连接作用(比如说吧struct和hibernate粘合在一起运用);
让我们的企业开发更快,更简洁。

轻量级的控制反转(IOC)和面向切面的(AOP)框架

  1. 轻量级:从大小和开销方面而言Spring都是轻量级的
  2. IOC:通过控制反转(ioc)的技术来达到松耦合的目的
  3. AOP:分离应用的业务逻辑和系统级服务进行内聚式的开发
  4. 容器:包含并管理应用对象(Bean)的配置和生命周期
  5. 框架:简单的组件配置,组合成复杂的应用

Aop的理解?

将程序中的交叉业务逻辑(比如安全,日志,事务等),封装成一个切面,然后注入到目标对象(具体业务逻辑)中去。
Aop可以对某个对象或某些对象的功能进行增强,比如对象中的方法进行增强,可以在执行某个方法之前、或之后执行额外的做一些事情。

Ioc的理解?

容器概念:ioc就是一个容器,实际上就是一个map(key,value),里面存的是各种对象(在xml里配置的bean节点,@repository,@service,@controller,@component)

在项目启动的时候会读取配置文件里的bean节点,根据全限定类名使用反射创建对象放到map里,或者扫描到打上上述注解的类通过反射创建对象放到map里。
然后系统启动的时候读取xml节点的ref属性根据id,或者根据注解(@autowired,@resource)在代码里需要用到里面的对象时,通过DI注入

控制反转:
引入Ioc容器之前:对象A依赖对象B,主动创建对象B
引入ioc容器之后:对象A需要对象B,ioc容器主动创建对象B注入到对象A需要的地方
控制反转:前后对比,对象A获取依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒。
对象的控制权全部上缴给"第三方"IOC容器,IOC容器成为了系统的关键核心,关联系统中的所有对象一起发挥作用。

依赖注入:实现IOC的方法,有IOC容器在运行期间,动态将某种依赖关系注入到对象之中。

Bean

Bean是什么?

bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。

  • 基于 XML 的配置文件

  • 基于注解的配置

  • 基于 Java 的配置

BeanFactory和ApplicationContext有什么区别?

ApplicationContext是BeanFactory的子接口
ApplicationContext提供更完整的功能:

  1. 继承了MessageSource,因此支持国际化。
  2. 统一的资源文件访问形式。
  3. 提供在监听器中注册bean的事件。
  4. 同时加载多个配置文件。
  5. 载入多个(有继承关系)上下文,使得每一个上下文都专注一个特定的层次,比如应用的web层。
  • BeanFactory采用延迟加载形式注入Bean,即只有在使用某个Bean(调用getBean()),才对该Bean进行加载实例化。启动后只有在使用的时候才能发现存在的Spring的配置问题,
  • ApplicationContext,容器启动时,一次性创建了所有的Bean(启动时就可以发现Spring中存在的配置错误,有利于检查所依赖属性是否注入),Application启动后预载入所有的单实例Bean,需要的时候不用等待。
  • Application占用内存不足,程序配置Bean较多时,启动越慢。
  • BeanFactory通常以编程方式创建,ApplicationContext可以以声明的方式启动,如使用ContextLoader
  • 都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,区别:BeanFactory需要手动注册,ApplicationContext则是自动注册

BeanPostProcessor接口回调对应的主体是bean,其可以在bean实例化以后但是在调用其初始化方法前后进行回调以达到对bean进行处理的效果。
BeanFactoryPostProcessor的主体是BeanFactory,并且该接口中只定义了一个方法,其将会在ApplicationContext内部的BeanFactory加载完bean的定义后,但是在对应的bean实例化之前进行回调。所以通常我们可以通过实现该接口来对实例化之前的bean定义进行修改。

Bean生命周期?

  1. 解析类得到BeanDefinition
  2. 如果有多个构造函数,则要推断构造方法
  3. 实例化得到一个对象
  4. 对对象中加了@Autowired注解的属性进行属性填充
  5. 回调Aware方法,比如BeanNameAware,BeanFactoryAware(Aware接口也是为了能够感知到自身的一些属性
  6. 调用BeanPostProcessor的初始化前的方法
  7. 调用初始化方法init
  8. 调用BeanPostFactoryProcessor初始后的方法,在这里会进行Aop
  9. 如果创建的Bean是单例则会放入单例池
  10. 使用bean
  11. Spring容器关闭时调用DisposableBean的Destory方法

Bean作用域

singleton 默认:每个容器只有一个bean的实例,单例的模式由BeanFactory自身来维护。该对象的生命周期与Spring Ioc容器一致(第一次被注入时创建)
prototype 原型模式,为每一个bean请求创建一个实例。在每次注入时都会创建一个新的对象
request  bean被定义为在每个HTTP请求中创建一个单例对象,也就是说单个请求中都会复用这一个单例对象
session 与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效
application bean被定义为在servletContext的声明周期中复用一个单例对象
websocket bean被定义为在websocket的生命周期复用一个单例对象
global-session 全局作用域

Spring单例Bean是线程安全?

非线程安全,没有进行多线程封装处理。

怎么保证?改变bean的作用域,把singleton改为prototype,相当于每次请求是new Bean()

上一篇:SpringBoot成长记6:准备SpringContext容器


下一篇:spring-boot源码分析之beanFactory · 肆