今每天气不错,我怀着自信的笑容来到某个大厂的研发中心,开启面试的一天。首先我不是毫无准备的,什么java并发,多线程,jvm,分布式,数据库都准备的妥妥的,没想到今天的面试的主题是spring。不过还好,我也准备了...门开了,走来一位拿着mac本,戴眼镜的年轻的小伙子,跟我差很少大吧。而后他示意我坐下,礼貌的说:“欢迎来咱们公司面试,今天咱们就聊聊spring吧”...前端
面试官:你说下什么是spring?java
我:spring是一种轻量级开发框架,旨在提升开发人员的开发效率以及系统的可维护性。咱们通常说的spring框架指的是Spring Framework,它是不少模块的集合,使用这些模块能够很方便的协助咱们开发。这些模块是:核心容器、数据访问/集成、Web、AOP(面向切面编程)、工具、消息和测试模块。好比:Core Container中的Core组件是Spring全部组件的核心,Beans组件和Context组件是实现IOC和依赖注入的基础,AOP组件用来实现面向切面编程。mysql
面试官:使用Spring框架有什么好处呢?程序员
我:框架能更让咱们高效的编程以及更方便的维护咱们的系统。web
面试官:那IOC与new对象有什么区别吗面试
我:这就是正转与反转的区别。传统应用程序是由咱们本身在对象中主动控制去直接获取依赖对象,也就是正转。而反转则是容器来帮助咱们建立并注入依赖对象。spring
面试官:好的,那IOC有什么优缺点吗?sql
我:优势:很明显,实现了组件之间的解耦,提升程序的灵活性和可维护性。缺点:对象生成由于是反射编程,在效率上有些损耗。但相对于IOC提升的维护性和灵活性来讲,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。数据库
面试官:spring管理这么多对象,确定须要一个容器吧。你能说下对IOC容器的理解吗?编程
我:首先来解释下容器:在每一个框架中都有个容器的概念,所谓的容器就是将经常使用的服务封装起来,而后用户只须要遵循必定的规则就能够达到统1、灵活、安全、方便和快速的目的。
我:而后IOC容器是具备依赖注入功能的容器,负责实例化、定位、配置应用程序中的对象以及创建这些对象间的依赖。
面试官:那你能说下IOC容器是怎么工做的吗?
我:首先说下两个概念。
@Test
public void testHelloWorld() {
//一、读取配置文件实例化一个IoC容器
ApplicationContext context = new ClassPathXmlApplicationContext("helloworld.xml");
//二、从容器中获取Bean,注意此处彻底“面向接口编程,而不是面向实现”
HelloApi helloApi = context.getBean("hello", HelloApi.class);
//三、执行业务逻辑
helloApi.sayHello();
}
复制代码
日志处理方式 | 实现方式 | 优缺点 |
---|---|---|
硬代码编写 | ||
![]() |
处理代码相同,代码强耦合 | |
抽离方法,代码复用 | ||
![]() |
手动插入代码,代码强耦合 | |
aop | ||
![]() |
横向的功能抽离出来造成一个独立的模块,低耦合 |
面试官:那你知道spring aop的原理吗?
我:spring aop就是基于动态代理的,若是要代理的对象实现了某个接口,那么spring aop会使用jdk proxy,去建立代理对象,而对于没有实现接口的对象,就没法使用jdk的动态代理,这时spring aop会使用cglib动态代理,这时候spring aop会使用cglib生成一个被代理对象的子类做为代理。
我:关于动态代理的原理能够参考个人这篇文章:juejin.im/post/5cea01…
面试官:那你知道Spring Aop和AspecJ Aop有什么区别吗?
我:Spring AOP属于运行时加强,而AspectJ是编译时加强。Spring Aop基于代理,而AspectJ基于字节码操做。Spring Aop已经集成了AspectJ,AspectJ应该算得上Java生态系统中最完整的AOP框架了。AspectJ相对于Spring Aop功能更增强大,可是Spring AOP相对来讲更简单。若是咱们的切面比较少,那么二者性能差别不大。可是,当且切面太多的话,最好选择AspectJ,它比Spring Aop快不少。
面试官:你对Spring中的bean了解吗?都有哪些做用域?
我:Spring中的Bean有五种做用域:
@Transactional
@Override
public void save(User user1, User user2) {
new Thread(() -> {
saveError(user1, user2);
System.out.println(1 / 0);
}).start();
}
复制代码