深入剖析Spring创建Bean源码,揭秘背后的奥秘
2023-11-08 09:09:11
Spring作为一款广受欢迎的Java应用程序框架,以其灵活、轻量、易于使用的特性著称。Spring的IoC(控制反转)容器是其核心组件之一,负责管理和创建Bean。
Spring创建Bean的过程涉及多个步骤,包括:
- Bean查找 :Spring会扫描应用程序上下文中标有特定注解的类,如@Component、@Service、@Repository等,并将这些类注册为Bean。
- Bean实例化 :Spring会根据Bean的类型决定如何实例化Bean。对于普通类,Spring会使用Java的反射机制创建Bean实例;对于FactoryBean,Spring会调用FactoryBean的getObject()方法创建Bean实例。
- 依赖注入 :Spring会根据Bean的属性配置为其注入依赖项。依赖项可以是其他Bean、基本类型或表达式。
- Bean后置处理 :在Bean实例化之后,Spring会调用BeanPostProcessor的postProcessBeforeInitialization()和postProcessAfterInitialization()方法,对Bean进行后置处理。
- Bean初始化 :Spring会调用Bean的初始化方法,如init()或afterPropertiesSet()方法,对Bean进行初始化。
- 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