返回

深入剖析Spring创建Bean源码,揭秘背后的奥秘

后端

Spring作为一款广受欢迎的Java应用程序框架,以其灵活、轻量、易于使用的特性著称。Spring的IoC(控制反转)容器是其核心组件之一,负责管理和创建Bean。

Spring创建Bean的过程涉及多个步骤,包括:

  1. Bean查找 :Spring会扫描应用程序上下文中标有特定注解的类,如@Component、@Service、@Repository等,并将这些类注册为Bean。
  2. Bean实例化 :Spring会根据Bean的类型决定如何实例化Bean。对于普通类,Spring会使用Java的反射机制创建Bean实例;对于FactoryBean,Spring会调用FactoryBean的getObject()方法创建Bean实例。
  3. 依赖注入 :Spring会根据Bean的属性配置为其注入依赖项。依赖项可以是其他Bean、基本类型或表达式。
  4. Bean后置处理 :在Bean实例化之后,Spring会调用BeanPostProcessor的postProcessBeforeInitialization()和postProcessAfterInitialization()方法,对Bean进行后置处理。
  5. Bean初始化 :Spring会调用Bean的初始化方法,如init()或afterPropertiesSet()方法,对Bean进行初始化。
  6. Bean销毁 :当Bean不再需要时,Spring会调用Bean的销毁方法,如destroy()或doDestroy()方法,对Bean进行销毁。

掌握Spring创建Bean的源码对于深入理解Spring IoC容器的工作原理至关重要。本文将通过分析Spring源码,详细讲解Spring创建Bean的各个步骤,并提供相应的代码示例。

Spring创建Bean的入口

Spring创建Bean的入口是AnnotationConfigApplicationContext类的preInstantiateSingletons()方法。这个方法会在Spring IoC容器启动时被调用,负责实例化所有单例Bean。

public void preInstantiateSingletons() {
   ...
   // 循环遍历BeanDefinitionMap,实例化单例Bean
   for (Map.Entry<String, BeanDefinition> entry : this.beanDefinitionMap.entrySet()) {
      String beanName = entry.getKey();
      BeanDefinition bd = entry.getValue();
      ...
      if (bd.isSingleton()) {
         getBean(beanName);
      }
   }
   ...
}

Bean的查找

Spring会扫描应用程序上下文中标有特定注解的类,如@Component、@Service、@Repository等,并将这些类注册为Bean。Spring使用类路径扫描器(ClassPathScanner)来扫描应用程序上下文,查找标有特定注解的类。

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
   ...
   // 注册默认过滤器
   addIncludeFilter(new AnnotationTypeFilter(Component.class));
   addIncludeFilter(new AnnotationTypeFilter(Service.class));
   addIncludeFilter(new AnnotationTypeFilter(Repository.class));
   ...
}

Spring还提供了多种自定义过滤器,允许开发者根据自己的需要来自定义Bean的查找。

Bean的实例化

Spring根据Bean的类型决定如何实例化Bean。对于普通类,Spring使用Java的反射机制创建Bean实例;对于FactoryBean,Spring会调用FactoryBean的getObject()方法创建Bean实例。

protected Object createBeanInstance(NameAware nameAware, BeanDefinition beanDefinition, Object[] args) {
   ...
   Class<?> beanClass = beanDefinition.getBeanClass();
   ...
   if (beanDefinition instanceof AbstractBeanDefinition) {
      AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDefinition;
      try {
         // 使用反射机制创建Bean实例
         return beanClass.getDeclaredConstructor().newInstance();
      } catch (Exception e) {
         throw new BeanInstantiationException(beanDefinition.getBeanClass(), "Failed to instantiate using constructor");
      }
   } else {
      // 调用FactoryBean的getObject()方法创建Bean实例
      return getBeanPostProcessor().postProcessFactoryBean(factoryBean.getObject(), beanDefinition.getBeanClass());
   }
   ...
}

依赖注入

Spring根据Bean的属性配置为其注入依赖项。依赖项可以是其他Bean、基本类型或表达式。Spring使用依赖注入器(DependencyInjector)将依赖项注入到Bean中。

public void inject(Object target, String beanName, BeanDefinition beanDefinition) {
   ...
   final PropertyValues pvs = beanDefinition.getPropertyValues();
   if (pvs.isEmpty()) {
      return;
   }
   PropertyValue[] propertyValues = pvs.getPropertyValues();
   for (PropertyValue propertyValue : propertyValues) {
      ...
      // 获取依赖项
      Object dependency = beanFactory.getBean(propertyValue.getName());
      ...
      // 将依赖项注入到Bean中
      target.getClass().getDeclaredField(propertyValue.getName()).set(target, dependency);
   }
   ...
}

Spring还提供了多种依赖注入方式,允许开发者根据自己的需要来自定义依赖注入。

Bean的后置处理

在Bean实例化之后,Spring会调用BeanPostProcessor的postProcessBeforeInitialization()和postProcessAfterInitialization()方法,对Bean进行后置处理。

public Object postProcessBeforeInitialization(Object bean, String beanName) {
   ...
   // 对Bean进行后置处理
   ...
   return bean;
}

public Object postProcessAfterInitialization(Object bean, String beanName) {
   ...
   // 对Bean进行后置处理
   ...
   return bean;
}

Spring提供了多种BeanPostProcessor,允许开发者根据自己的需要来自定义Bean的后置处理。

Bean的初始化

Spring会调用Bean的初始化方法,如init()或afterPropertiesSet()方法,对Bean进行初始化。

public void initializeBean(BeanDefinition beanDefinition, Object bean) {
   ...
   // 调用Bean的初始化方法
   invokeInitMethods(beanName, bean, bd);
   ...
}

protected void invokeInitMethods(String beanName, Object bean, BeanDefinition bd) {
   ...
   // 调用Bean的init()方法
   if (bd.getInitMethodName() != null) {
      invokeCustomInitMethod(beanName, bean, bd);
   }
   // 调用Bean的afterPropertiesSet()方法
   if (bd instanceof