前几天面了一个小厂,被深入了问框架原理和执行流程,场面极其尴尬,被面试官吊着锤,怎么说呢?很多知识自己记忆的比较碎片化,也没能经得住深入的考察。
赶紧补补课,整理了一下常见的考点,但是这毕竟还是不够深入,有时间我会慢慢的深入源码多看看,深入dubug一下,然后再来总结。
1. Spring 是什么?
Spring是一个开源的轻量级、侵入性小、松散耦合的开发框架,能够与多种框架进行集成,并进行不同的操作,可以称之为框架的框架。
具有以下几个模块:
- Spring 核心容器:
- Spring Core:核心类库,所有功能都依赖于该类库,提供IOC和DI服务;
- Spring Beans
- Spring SpEL(Spring Expression Language)
- Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);
- Data Access / Integration:数据访问框架集成
- JDBC
- ORM
- JMS:消息
- Transaction:事务
- Web模块:提供了基本的面向Web的综合特性,提供对常见框架如Struts2的支持,Spring能够管理这些框架,将Spring的资源注入给框架,也能在这些框架的前后插入拦截器;
- WebSocket
- Servlet
- Web
- AOP:面向切面编程
- Test:测试框架
2. 对 Spring Ioc 的理解:
- Inversion of Control(控制反转)
- 是一种设计思想,在Java开发中,将你设计好的对象交给容器控制,而不是显示地用代码进行对象的创建。
- 把创建和查找依赖对象的控制权交给 IoC 容器,由 IoC 容器进行注入、组合对象。这样对象与对象之间是松耦合、便于测试、功能可复用(减少对象的创建和内存消耗),使得程序的整个体系结构可维护性、灵活性、扩展性变高。
使用 IoC 的好处:
- 资源集中管理,实现资源的可配置和易管理
- 降低了资源的依赖程度,即松耦合
- 便于测试
- 功能可复用(减少对象的创建和内存消耗)
- 使得程序的整个体系结构可维护性、灵活性、扩展性变高
DI 是什么?
- (Dependency Injection)依赖注入,是 IoC 容器装配、注入对象的一种方式。通过依赖注入机制,简单的配置即可注入需要的资源,完成自身的业务逻辑,不需要关心资源的出处和具体实现。
Spring的IoC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。
3. 对Spring AOP 的理解:
- Aspect Oriented Programming,面向切面编程。
- 作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块。减少系统中的重复代码,降低了模块间的耦合度,提高系统的可维护性。可用于权限认证、日志、事务处理。
- AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ,动态代理则以Spring AOP为代表。
- AspectJ是静态代理,也称为编译时增强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
- Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式:
JDK动态代理
和CGLIB动态代理
:
- JDK动态代理只提供接口的代理,不支持类的代理,要求被代理类实现接口。JDK动态代理的核心是
InvocationHandler
接口和Proxy类,在获取代理对象时,使用Proxy类来动态创建目标类的代理类(即最终真正的代理类,这个类继承自Proxy并实现了我们定义的接口),当代理对象调用真实对象的方法时,InvocationHandler
通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;InvocationHandler
的invoke(Object proxy,Method method,Object[] args)
:proxy是最终生成的代理对象; method 是被代理目标实例的某个具体方法; args 是被代理目标实例某个方法的具体入参, 在方法反射调用时使用。
- 如果被代理类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
- 静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
Spring AOP 里面的几个关键名词:
- 连接点(Join point):指程序运行过程中所执行的方法。在Spring AOP中,一个连接点总代表一个方法的执行。
- 切面(Aspect):被抽取出来的公共模块,可以用来会横切多个对象。Aspect切面可以看成 Pointcut切点 和 Advice通知 的结合,一个切面可以由多个切点和通知组成。
- 切点(Pointcut):切点用于定义 要对哪些Join point进行拦截。
切点分为execution方式和annotation方式。execution方式可以用路径表达式指定对哪些方法拦截,比如指定拦截add*、search*。annotation方式可以指定被哪些注解修饰的代码进行拦截。
- 通知(Advice):指要在连接点(Join Point)上执行的动作,即增强的逻辑,比如权限校验和、日志记录等。通知有各种类型,包括Around、Before、After、After returning、After throwing。
- 目标对象(Target):包含连接点的对象,也称作被通知(Advice)的对象。 由于Spring AOP是通过动态代理实现的,所以这个对象永远是一个代理对象。
- 织入(Weaving):通过动态代理,在目标对象(Target)的方法(即连接点Join point)中执行增强逻辑(Advice)的过程。
- 引入(Introduction):添加额外的方法或者字段到被通知的类。Spring允许引入新的接口(以及对应的实现)到任何被代理的对象。例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。