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