深入理解Spring-IOC
作者:COLDE 文章内容输出来源:拉勾教育Java高薪训练营课程
-
IOC概述
1.1 什么是IOC
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
传统开发模式
传统开发模式.pngIoC模式
IOC容器.png1.2 IOC解决了什么问题
演变.png-
OOP开发模式
UserService和UserDao深度耦合,当UserDao发生变更时,会联动引发UserService的变更,高层模块依赖于底层模块,违法依赖倒置原则。
-
IOP开发模式
将UserDao抽象为IUserDao接口,UserService依赖于IUserDao抽象接口,不依赖其具体实现,但在创建IUserDao实例对象时(new UserDaoImpl),UserService还是依赖其实例对象。
-
IoC开发模式
对象之间只依赖于抽象规则,不依赖其具体实现,具体实例的创建权限交由IOC容器进行控制,极大的降低代码的耦合度
2. Spring IoC深入分析
IoC容器是Spring的核心模块,是抽象了对象管理、依赖关系管理的框架解决方案。BeanFactory为顶层容器,不能被实例化,它定义了所有IoC容器必须遵从的一套原则,具体的容器实现可以增加额外的功能。以Spring Boot默认加载容器AnnotationConfigApplicationContext为例,其继承体系如下:
BeanFactory容器继承体系.png其中GenericApplicationContext持有一个BeanFactory的默认实现类DefaultListableBeanFactory的实例对象,Spring Context使用代理模式使用该实例替它执行BeanFactory接口定义的功能。DefaultListableBeanFactory继承体系如下:
DefaultListableBeanFactory继承体系.png
源码分析
- 源码分析用例
public class AnnotationConfigApplicationContextTest {
// 声明配置Bean
@Configuration
public class BeanConfiguration {
@Bean
public TestBean getTestBean(){
return new TestBean();
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfiguration.class);
TestBean bean = applicationContext.getBean(TestBean.class);
System.out.println(bean);
}
}
- Spring上下文容器初始化
public class GenericApplicationContext{
public GenericApplicationContext() {
// 创建BeanFactory的默认容器实现类,有关BeanFacory相关的大部分功能通过代理模式使用该实例进行实现
this.beanFactory = new DefaultListableBeanFactory();
}
}
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
// 配置Bean处理器
this.reader = new AnnotatedBeanDefinitionReader(this);
// 包扫描处理器
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
// 注解方式上下文创建入口
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 重载构造方法,创建reader、scanner,调用父类构造方法创建DefaultListableBeanFactory的实例对象
this();
// 注册配置bean
register(componentClasses);
// 容器初始化核心方法
refresh();
}
public void register(Class<?>... componentClasses) {
this.reader.register(componentClasses);
}
public void scan(String... basePackages) {
this.scanner.scan(basePackages);
}
}
- register:注册配置Bean
public class AnnotatedBeanDefinitionReader {
// 注册bean入口
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 包装为BeanDefinition对象
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
// 设置创建bean对象时的钩子方法
abd.setInstanceSupplier(supplier);
// 获取bean的Scope属性
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 获取beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 处理bean上的注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 源码略...
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//调用BeanDefinitionReaderUtils.registerBeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
public abstract class BeanDefinitionReaderUtils {
}
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
//beanName注册
String beanName = definitionHolder.getBeanName();
// 调用DefaultListableBeanFactory的registerBeanDefinition方法
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//别名注册
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
public class DefaultListableBeanFactory{
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition){
// 其他逻辑代码略
// 将bean信息包装类放置到beanDefinitionMap中
// 至此,bean注册逻辑完成
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
}
}
- refresh:容器初始化核心逻辑分析
public class AbstractApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1、预处理设置启动时间活动标记
prepareRefresh();
// 2、获取BeanFactory;默认实现是DefaultListableBeanFactory,由GenericApplicationContext构造方法中创建
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3、BeanFactory的预准备⼯作
prepareBeanFactory(beanFactory);
try {
// 4、BeanFactory准备⼯作完成后进⾏的后置处理⼯作
postProcessBeanFactory(beanFactory);
// 5.1、实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
// 5.2、解析配置类中Bean信息并注册
invokeBeanFactoryPostProcessors(beanFactory);
// 6、注册BeanPostProcessor(Bean的后置处理器)
registerBeanPostProcessors(beanFactory);
// 7、初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
initMessageSource();
// 8、初始化事件派发器
initApplicationEventMulticaster();
// 9、钩子方法,⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
onRefresh();
// 10、注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean
registerListeners();
// 11、初始化所有剩下的⾮懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
// 12、完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事件
finishRefresh();
}
catch (BeansException ex) { }
}
}
}
- 解析配置类中的Bean信息并注册
// 核心代码
class ConfigurationClassBeanDefinitionReader {
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
// 解析配置类中的bean配置方法
loadBeanDefinitionsForBeanMethod(beanMethod);
// 最终调用DefaultListableBeanFactory的registerBeanDefinition进行bean的注册
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
}
}
- 循环依赖对象创建分析
//开始初始化Bean
DefaultListableBeanFactory#preInstantiateSingletons
AbstractBeanFactory#getBean
AbstractBeanFactory#doGetBean
// #从三级缓存中获取Bean,解决循环依赖关键位置,第一次返回null
DefaultSingletonBeanRegistry#getSingleton
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存获取,获取成功则对象已经创建成功
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从二级缓存取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 从三级缓存取,获取成功则从三件缓存**剪切**对象到二级缓存
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
// 创建实例bean,还未对实例bean对象属性进行赋值
AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#createBeanInstance
// 将实例bean包装未ObjectFactory对象,放入三级缓存提前暴露对象 DefaultSingletonBeanRegistry#addSingletonFactory(ObjectFactory)
// 属性填充
AbstractAutowireCapableBeanFactory#populateBean
AbstractAutowireCapableBeanFactory#autowire*
AbstractBeanFactory#getBean
AbstractBeanFactory#doGetBean
// 继续尝试从三级缓存中获取对象,如获取失败,执行bean创建逻辑,并放入缓存供依赖对象获取填充
DefaultSingletonBeanRegistry#getSingleton
-
循环依赖流程说明
Spring-IOC-循环依赖.png
总结
Spring IoC将对象的创建权限和对象之间的依赖关系交由容器进行管理,使得代码之间的耦合度进一步降低,业务开发时,一旦对象之间的抽象关系确立,底层业务逻辑发生业务变更,无需修改上层逻辑即可实现业务的变更,达到对象之间只依赖与抽象而不依赖于具体实现。