一、什么是IoC(控制反转)?
IoC(Inversion of Control,控制反转)是一种设计模式,它将对象的创建、管理和组装的控制权从应用程序代码中转移给IoC容器。
在IoC模式中,应用程序不会直接创建和管理对象,而是通过IoC容器来获取所需要的对象实例。IoC容器负责创建、管理和组装对象,应用程序只需要使用这些对象即可。Spring框架是一个经典的IoC容器实现,它使用BeanFactory和ApplicationContext等核心容器来实现IoC功能。
二、什么是依赖注入(DI)?
依赖注入(Dependency Injection,DI)是一种实现IoC的方式。它通过将依赖关系从应用程序代码中分离出来,使得应用程序更加松散耦合、易于测试和维护。
在DI模式中,应用程序不会直接创建和管理对象,而是通过IoC容器来获取所需要的对象实例,并将这些对象实例注入到应用程序代码中所需的位置上。
Spring框架通过构造器注入、属性注入和方法注入等方式实现依赖注入。
三、什么是AOP(面向切面编程)?
AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,它可以将应用程序中的通用功能(如日志记录、性能监控、安全性检查等)从业务逻辑中分离出来,实现横向抽取和复用。
在AOP模式中,通用功能被封装成一个切面(Aspect),然后通过切点(Pointcut)来定义应用程序中哪些位置需要被切面拦截,从而实现通用功能的横向抽取和复用。
四、Spring框架的事务管理机制是如何实现的?
Spring框架的事务管理机制是基于AOP实现的。Spring通过AOP技术将事务管理逻辑与业务逻辑分离,使得事务管理逻辑可以独立于业务逻辑进行配置和修改。
Spring框架提供了两种事务管理方式:编程式事务管理和声明式事务管理。
编程式事务管理是通过编写代码实现事务控制的方式,需要开发人员显式地在代码中调用事务管理API来控制事务的提交和回滚。
声明式事务管理是通过配置方式实现事务控制的方式,开发人员只需要通过配置文件或注解等方式声明事务管理信息,Spring框架就会自动将其转换成AOP切面,并将其织入到应用程序中相应的方法或类中。
五、Spring框架的Bean生命周期是怎样的?
Spring框架的Bean生命周期可以分为以下几个阶段:
实例化(Instantiation):Spring容器会通过Java反射机制或CGLIB等方式创建Bean的实例。
属性赋值(Population):Spring容器会将Bean实例的属性值设置为配置文件或注解等方式中指定的值。
BeanPostProcessor处理(BeanPostProcessor):Spring容器会在实例化Bean和属性赋值之后,调用实现了BeanPostProcessor接口的类中的postProcessBeforeInitialization和postProcessAfterInitialization方法,对Bean实例进行定制和增强。
初始化(Initialization):Spring容器会调用实现了InitializingBean接口的类中的afterPropertiesSet方法,对Bean进行初始化。
销毁(Destruction):当Spring容器关闭时,会调用实现了DisposableBean接口的类中的destroy方法,对Bean进行销毁。
六、Spring框架中的循环依赖问题是如何解决的?
Spring框架中的循环依赖问题是指两个或者多个Bean之间存在相互依赖的情况,从而导致Bean无法正常实例化和依赖注入的问题。
Spring框架通过“提前暴露”和“三级缓存”等机制来解决循环依赖问题。
2.1“提前暴露”是指在Bean实例化过程中,当存在循环依赖问题时,Spring容器会提前暴露一个半成品的Bean实例,然后等待该Bean实例的依赖注入完成后,再对该Bean实例进行剩余的初始化工作。
2.2“三级缓存”是指在Bean实例化过程中,Spring容器会维护三个缓存区,分别存放已经实例化的Bean,正在实例化的Bean和还未实例化的Bean。当Spring容器检测到循环依赖问题时,会将正在实例化的Bean放入到第二级缓存中,并在第三级缓存中存储Bean定义信息。当Bean实例化完成后,会将该Bean实例放入第一级缓存中,并从第二级缓存中移除该Bean实例。
七、Spring框架中的AOP是如何实现的?
Spring框架中的AOP是通过动态代理实现的。在Spring容器中,每个Bean都有一个与之对应的代理对象,当调用该Bean的方法时,Spring容器会自动将代理对象织入到方法调用链中,从而实现对该方法的增强。
Spring框架中的动态代理分为两种方式:JDK动态代理和CGLIB动态代理。
JDK动态代理是基于接口的代理,只能代理实现了接口的类,而CGLIB动态代理则是基于继承的代理,可以代理没有实现接口的类。
在Spring框架中,当一个Bean实现了接口时,Spring容器会使用JDK动态代理,否则会使用CGLIB动态代理。同时,Spring框架还支持注解的方式和XML配置方式来声明和配置AOP切面。