《剑指Java面试-Offer直通车》--Java框架Spring

《剑指Java面试-Offer直通车》--Java框架Spring_第1张图片

目录

IOC

一、IOC原理

依赖注入的方式

依赖倒置原则、IOC、DI和Spring IOC容器的关系

二、Spring IOC的应用

spring IOC支持的功能

spring IOC容器的核心接口

getBean方法的代码逻辑

Spring Bean的作用域

Spring Bean的生命周期

AOP

一、AOP的介绍和使用

AOP的三种织入方式

AOP的主要名词概念

Advice的种类

二、AOP的原理

AOP的实现:JdkProxy和Cglib

代理模式:接口+真实实现类+代理类


IOC

一、IOC原理

IOC(Inversion of Control):控制反转,是Spring Core最核心部分。

需要先了解依赖注入DI(Dependency Inversion):把底层类作为参数传递给上层类,实现上层对下层的“控制”。

IOC的另外一种实现方式:依赖查找DL(Dependency Lookup),Apache Avalon和EJB就是利用DL实现的IOC。DL相对DI而言是更为主动的方法,在需要的时候通过调用框架提供的方法来获取对象。获取时需要通过提供相关的配置文件路径、key等信息来确定获取对象的状态。DL已经被抛弃,因为它需要用户自己去使用API查找资源和组装对象,有侵入性。DI是当今IOC的主流实现方式。

  • 依赖注入的方式

Set注入:实现特定属性的public setter()方法来让IOC容器调用注入所依赖类型的对象

接口注入:实现特定的接口来让IOC容器注入所依赖类型的对象

构造函数注入:实现特定参数的构造函数,在创建对象时让IOC注入所依赖类型的对象

注解注入:通过Java注解机制,让IOC容器注入所依赖类型的对象。例如Spring框架里的Autowire标签都是能够实现注解功能的

  • 依赖倒置原则、IOC、DI和Spring IOC容器的关系

依赖倒置原则是一种思想,大致含义是高层模块不应该依赖低层模块,两者都应该依赖其抽象。

有了依赖倒置原则的指导才有了IOC的思路,实现IOC思路离不开DI依赖注入的支撑。spring框架基于IOC提出了容器的概念,对于IOC来说,最重要的就是容器,容器管理着Bean的生命周期,控制着Bean的依赖注入。

因为采用依赖注入,在初始化过程中会写大量new,容器解决这个问题。容器自动对代码进行初始化,只需要维护一个Configuration(可以是xml,也可以是一段代码)而不用每次初始化时都要亲手去写一大段初始化的代码。IoC Container的第二个好处是我们在创建实例的时候不需要了解其中的细节。从最上层开始往下找依赖关系,到达最底层之后再往上一步一步new,类似深度遍历。

参考:Spring IoC和AOP的实现原理解析

 

二、Spring IOC的应用

spring启动时读取应用程序提供的bean配置信息,并在Spring容器中生成一份相应的bean配置表,根据注册表去实例化bean,装配好bean之间的依赖关系,为上层提供准备就绪的运行环境。spring提供配置文件描述bean以及bean之间的依赖关系,利用Java语言的反射功能实例化bean并建立bean之间的依赖关系。

  • spring IOC支持的功能

依赖注入、依赖检查、自动装配、支持集合、指定初始化方法和销毁方法、支持回调方法(需要实现Spring接口,这种实现方式带有侵入性)

  • spring IOC容器的核心接口

BeanFactory、ApplicationContext

BeanDefinition主要用来描述Bean的定义,Spring容器在启动的时候会将xml或者注解里bean的定义解析成spring内部的BeanDefinition。

BeanDefinitionRegistry接口提供向容器手工注册BeanDefinition对象的方法。

BeanFactory是Spring框架最核心的接口,提供IOC的配置机制;包含Bean的各种定义,便于实例化Bean;建立Bean之间的依赖关系;Bean生命周期的控制。

BeanFactory的体系结构:

《剑指Java面试-Offer直通车》--Java框架Spring_第2张图片

 

BeanFactory与ApplicationContext的比较

ApplicationContext是BeanFactory的子接口之一。BeanFactory是spring框架的基础设施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者

ApplicationContext继承至多个接口:

1)BeanFactory:能够管理装配Bean

2)ResourcePatternResolver:能够加载资源文件

3)MessageSource:管理Message,能够实现国际化等功能

4)ApplicationEventPublisher:能够注册监听器,实现监听机制

Bean如何装载到IOC中,如何从IOC获取Bean实例并使用,IOC容器的创建配置,Bean如何获取的底层原理

  • getBean方法的代码逻辑

1)转换beanName

2)从缓存中加载实例

3)实例化Bean

4)检测parentBeanFactory

5)初始化依赖的Bean

6)创建Bean

  • Spring Bean的作用域

singleton:Spring的默认作用域,容器里拥有唯一的Bean实例。适合无状态的Bean

prototype:针对每个getBean请求,容器都会创建一个Bean实例。适合有状态的Bean(把Bean设置成prototype作用域需谨慎,频繁创建和销毁Bean是有开销的)

web容器支持另外三种作用域

request:会为每个Http请求创建一个Bean实例

session:会为每个session创建一个Bean实例

globalsession:会为每个全局Http Session创建一个Bean实例,该作用域仅对Portlet有效

  • Spring Bean的生命周期

创建过程

1)实例化Bean对象以及设置Bean属性

2)如果通过各种Aware接口声明依赖关系,则会注入Bean对容器基础设施层面的依赖。Aware接口是为了感知到自身的一些属性。容器管理的Bean一般不需要了解容器的状态和直接使用容器。在某些情况下,就需要在Bean中设定对容器的感知。Spring IOC容器也提供了该功能,它是通过特定的Aware接口来完成的。例如BeanNameAware可以在Bean中得到它在IOC容器中的Bean的实例的名字。

3)调用BeanPostProcessor的前置初始化方法postProcessorBeforeInitialization,主要作用是在Spring完成实例化之后对Spring容器实例化的Bean添加自定义的处理逻辑。

4)如果实现InitializingBean接口,则会调用afterPropertiesSet方法,做一些属性被设置后的自定义的事情。

5)调用Bean自身定义的init方法,做一些初始化相关的工作。

6)调用BeanPostProcessor的后置初始化方法postProcessAfterInitialization做Bean实例初始化化后的自定义工作。

7)Bean初始化完毕

销毁过程

若实现了DisposableBean接口,则会调用destory方法

若配置了destroy-method属性,则会调用其配置的销毁方法

 

AOP

一、AOP的介绍和使用

面向切面编程。软件工程有一个基本原则关注点分离,不同的问题交给不同的部分去解决,每部分专注解决自己的问题。面向切面编程AOP正是此种技术的体现。代码主要实现某种特定的业务逻辑,但往往不能专注于业务逻辑,写业务逻辑代码的同时还要写事务管理、缓存、日志等等通用块的功能。每个通用的功能都要和这些业务功能混在一起。为了将业务功能的关注点和通用化功能的关注点分离开来,就出现了AOP的技术。通用化功能代码的实现,对应的就是所谓的切面。业务功能代码和切面代码分开后,架构变得高内聚低耦合。确保功能的完整性,切面最终需要被合并到业务中(Weave)

  • AOP的三种织入方式

编译时织入,需要特殊的Java编译器,如AspectJ

类加载时织入,需要特殊的Java编译器,如AspectJ和AspectWerkz

运行时织入,Spring采用的方式,通过动态代理的方式,实现简单

  • AOP的主要名词概念

Aspect通用功能的代码实现

Target被织入Aspect的对象

Join Point可以作为切入点的机会,所有方法都可以作为切入点。

Pointcut Aspect实际被应用在Join Point,支持正则。

Advice类里面的方法以及这个方法如何织入到目标方法的方式

Weaving AOP的实现过程。AOP实现的过程中将切面应用到实际对象,从而创建一个新的代理对象的过程。

  • Advice的种类

前置通知(Before)

后置通知(AfterReturning)

异常通知(AfterThrowing)

最终通知(After)

环绕通知(Around)

 

二、AOP的原理

  • AOP的实现:JdkProxy和Cglib

由AopProxyFactory根据AdvisedSupport对象的配置来决定,默认策略如果目标类是接口,则用JDKProxy来实现,否则用后者。

JDKProxy通过反射接收被代理的类,并且要求被代理的类必须实现一个接口,JDK动态代理的核心是InvocationHandle接口和Proxy类。Cglib以继承的方式动态生成目标类的代理。目标类没有实现接口,SpringAOP就会使用Cglib来动态代理目标类,Cglib全称code generation lib,代码生成的类库,在运行时动态生成某个类的子类,通过修改字节码来实现代理。Cglib通过继承的方式实现动态代理,某个类被标记为final它是无法使用Cglib来做动态代理的。Cglib底层借助ASM实现,ASM是一种能够操作字节码的框架。反射机制在生成类的过程中比较高效;ASM在生成类之后的执行过程中比较高效。

  • 代理模式:接口+真实实现类+代理类

真实实现类和代理类要实现接口,实例化时使用代理类。Spring AOP需要做的是生成一个代理类,替换掉真实实现类来对外提供服务。

Spring里代理模式的实现:真实实现类的逻辑包含在了getBean方法里,getBean方法返回的实际上是Proxy类的实例。Proxy类实例是Spring采用JDK Proxy或者CGLib动态生成的。getBean方法用于查找或者实例化容器中的Bean,这也是为什么Spring AOP只能作用于Spring容器中Bean的原因。对于不是使用IOC管理的对象,Spring AOP无能为力。

 

 

你可能感兴趣的:(《剑指Java面试-Offer直通车》--Java框架Spring)