前言
spring 是当前最广泛使用的开源框架,而spring framework 则是spring全家桶的基础。spring framework最重要的是 IOC 和 AOP。其中 IOC 又是Spring framework 的基础。
今天我们要做的就是解析IOC,总的来说IOC有两点至关重要:1、创建bean容器;2、初始化bean。
源码分析
本文以JAVA_CONFIG(注解)来解读spring IOC 源码。
下面我们从一段简单的代码出发分析
配置类
@Configuration
@ComponentScan("com.zhouxh")
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(Main.class);
TestService testService = (TestService)applicationContext.getBean("testService");
testService.sayHi();
System.out.println("结束");
}
}
service类
package com.zhouxh.service;
import org.springframework.stereotype.Service;
@Service("testService")
public class TestService {
public void sayHi(){
System.out.println("hello spring");
}
}
通过注解@Configuration
将Main类标记为配置类,并通过@ComponentScan("com.zhouxh")
指定bean扫描路径。
Spring IoC容器的加载过程
脑图
1.实例化容器 AnnotationConfigApplicationContext
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Main.class);
该有参构造的简单说明:
- 可以接收多个配置类,不过一般情况下,只会传入一个配置类
- 这个配置类有两种情况,一种是传统意义上的带上
@Configuration
注解的配置类,还有一种是没有带上@Configuration,但是带有@Component
,@Import
,@ImportResouce
,@Service
,@ComponentScan
等注解的配置类,在Spring内部把前者称为Full配置类,把后者称之为Lite配置类。在本源码分析中,有些地方也把Lite配置类称为普通Bean。public AnnotationConfigApplicationContext(Class<?>... componentClasses) { // 调用无参构造函数 this(); // 注册配置类 register(componentClasses); // IOC 容器刷新接口 refresh(); }
this()
在通过this()方法调用无参构造函数时,会隐式的调用父类的构造函数
public AnnotationConfigApplicationContext() {
// 执行父类无参构造,设置bean工厂类
/**
* public GenericApplicationContext() {
* this.beanFactory = new DefaultListableBeanFactory();
* }
*/
// 设置读取配置类
this.reader = new AnnotatedBeanDefinitionReader(this);
// 设置扫描类,默认情况下没有使用,除非外部显示的调用scan()方法指定扫描路径
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotatedBeanDefinitionReader【beanDefinition读取器】
主要做了2件事情
- 注册内置BeanPostProcessor
- 注册相关的BeanDefinition
通过对new AnnotatedBeanDefinitionReader(this)
代码的追踪发现真正做事情的AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
由于该方法代码较多,这里只把最核心的代码贴出来。
在该方法中存在较多的类似的代码。其主要目的就是为了给容器添加内置组件if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); }
- 判断容器中是否已经存在了ConfigurationClassPostProcessor Bean
- 如果不存在(第一次运行必然不存在),就通过RootBeanDefinition的构造方法获得ConfigurationClassPostProcessor的BeanDefinition,RootBeanDefinition是BeanDefinition的子类
- 执行registerPostProcessor方法,registerPostProcessor方法内部就是注册Bean,当然这里注册其他Bean也是一样的流程。
该方法最终会将ContextAnnotationAutowireCandidateResolver,ConfigurationClassPostProcessor【bean的扫描和注册】
,CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor【@Autowired属性的自动注入】
,PersistenceAnnotationBeanPostProcessor 这5个组件添加到spring容器中。
register(componentClasses);
register 是将传入的配置类解析成beanDefinition,并注册到容器中。
包装成 BeanDefinition
判断条件是否满足 @condition
设置bean作用域
解析通用注解(@Lazy、@Primary、@DependsOn、@Role、@Description),并将属性设置到beanDefinition中
将beanDefinition注册到容器中
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { // 将beanClass 包装成 BeanDefinition AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); //判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } abd.setInstanceSupplier(supplier); // 设置bean作用域 spring 默认 singleton ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); // 解析通用注解(@Lazy、@Primary、@DependsOn、@Role、@Description),并将属性设置到beanDefinition中 AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { abd.setPrimary(true); } else if (Lazy.class == qualifier) { abd.setLazyInit(true); } else { abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } if (customizers != null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); // 将beanDefinition 添加到map缓存中 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }
refresh();
到这里为止,我们想要注入的testService类还没有被扫描,在上面的方法中只注册了默认的内置bean和配置类。
真正的重点代码在这个refresh()刷新方法中。
脑图
prepareRefresh();
开始刷新方法的准备工作,主要记录容器开始时间、启动标识之类的
需要注意的只有两行代码
//初始化属性,由字类覆盖实现
initPropertySources();
// 验证必要属性是否都已经被解析
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
initPropertySources
方法,我们可以继承该类并重写该方法,通过然后给Environment中添加某参数。
protected void initPropertySources() {
System.out.println("扩展initPropertySource");
//这里添加了一个username属性到Environment里面,以方便我们在后面用到
getEnvironment().getSystemProperties().put("username","bobo");
//这里要求Environment中必须包含username属性,如果不包含,则抛出异常
// 在这里设置会被getEnvironment().validateRequiredProperties();检验到。
getEnvironment().setRequiredProperties("username");
}
prepareBeanFactory(beanFactory)
给beanFactory添加必要的组件
需要关注的代码
// BeanFactory接口未在普通工厂中注册为可解析类型。 MessageSource注册为Bean(并发现用于自动装配)。
// 意味着以下4各类可以在任意组件中自动装配,第一个参数是自动装配的类型,第二个字段是自动装配的值
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
//添加一个后置处理器:ApplicationListenerDetector,此后置处理器实现了BeanPostProcessor接口
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
postProcessBeanFactory(beanFactory)
spring提供的拓展点,以便子类继承后对beanFactory进行个性化设置。
invokeBeanFactoryPostProcessors(beanFactory)
需关注如下代码:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory,
List<BeanFactoryPostProcessor> beanFactoryPostProcessors)
参数里的 beanFactoryPostProcessors
不是spring管理的 beanFactoryPostProcessor
而是从外部通过如下代码添加的,如果没有通过该方法添加 默认为空
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.addBeanFactoryPostProcessor(xxx);
invokeBeanFactoryPostProcessors方法中存在三段类似的代码,此处只粘贴一段进行分析
这三段相似代码意味着:BeanFactoryPostProcessor
按照代码先后顺序依次执行
- 首先执行实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors。bean定义后置注册处理器
- 然后执行实现Ordered接口的BeanDefinitionRegistryPostProcessors。
- 最后执行普通的bean定义注册后置处理器
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear();
invokeBeanDefinitionRegistryPostProcessors
以上代码大致逻辑为:选择出对应类型的BeanFactoryPostProcessor,然后通过invokeBeanDefinitionRegistryPostProcessors
方法扫描出需要注册的bean,并加入到注册表中。
调用invokeBeanDefinitionRegistryPostProcessors方法最终是调用processConfigBeanDefinitions
方法
该方法大致做以下几件事:
扫描已经注册的bean中被@Configuration修饰的配置类,获取他的扫描路径
将配置类排序
通过扫描路径,扫描路径下所有被@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean修饰的类和方法,并添加到对应的集合中。
从集合中去除beanDefinition 并注册。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); // 这里就是需要注册的所有bean 的 name String[] candidateNames = registry.getBeanDefinitionNames(); // 循环选择出需要注册bean中的配置类 @Configuration for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // Return immediately if no @Configuration classes were found if (configCandidates.isEmpty()) { return; } // 根据 @Order注解的排序 ,排位靠前的先注册 configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing application context SingletonBeanRegistry sbr = null; // 如果是单例的 if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton( AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } if (this.environment == null) { this.environment = new StandardEnvironment(); } ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { // 解析配置类,解析扫描路径下被@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean修饰的类和方法,并添加到对应的集合中。 parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } // 从对应的集合中取出将beanDefinition注册 this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); // 判断是否有新的bean注册,有就注册 if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<>(); for (ConfigurationClass configurationClass : alreadyParsed) { alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } for (String candidateName : newCandidateNames) { if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } candidateNames = newCandidateNames; } } while (!candidates.isEmpty()); // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); } if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { // Clear cache in externally provided MetadataReaderFactory; this is a no-op // for a shared cache since it'll be cleared by the ApplicationContext. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); } }
registerBeanPostProcessors(beanFactory)
实例化和注册beanFactory中扩展了BeanPostProcessor的bean。
例如:AutowiredAnnotationBeanPostProcessor
(处理被@Autowired注解修饰的bean并注入)RequiredAnnotationBeanPostProcessor
(处理被@Required注解修饰的方法)CommonAnnotationBeanPostProcessor
(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等
initMessageSource()【非IOC主线代码】
初始化国际化资源处理器
initApplicationEventMulticaster()
初始化创建事件多播器。
registerListeners()
注册监听器
以上两个方法【initApplicationEventMulticaster
/registerListeners
】和spring的事件监听机制密切相关。
onRefresh()
spring提供的拓展点,在springboot中有被使用
finishBeanFactoryInitialization()
完成上下文的bean工厂的初始化,初始化所有剩余的单例bean。
需要关注的核心代码
将所有beanDefinition设置为不可变,避免在实例化时,bean定义发生改变
实例化所有单例bean
// 将所有beanDefinition设置为不可变,避免在实例化时,bean定义发生改变 beanFactory.freezeConfiguration(); // 实例化所有单例bean beanFactory.preInstantiateSingletons();
DefaultListableBeanFactory.preInstantiateSingletons()
获取之前保存在beanDefinitionNames中的所有的beanName
循环bean,获取作用域为单例的bean
判断是否是factoryBean类型【bean继承FactoryBean,通过重写getObject(),自定义传入bean】
非factoryBean,通过getBean实例化,并将bean实例保存在容器(DefaultSingletonBeanRegistry.singletonObjects)中
调用所有实例化完成的bean的回调方法
public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // 获取之前保存在beanDefinitionNames中的beanName List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // 循环bean,获取单例bean for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 判断是否是factoryBean if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { // 没有继承FacetoryBean的bean,通过getBean实例化 getBean(beanName); } } } // 触发所有实例化bean的回调方法 for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
finishRefresh()
发布相应的事件
清除上下文资源缓存(如扫描中的ASM元数据)
初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)。
发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作
protected void finishRefresh() { // 清除上下文的资源缓存(例如来自扫描的ASM元数据)。 clearResourceCaches(); // 初始化生命周期处理器 initLifecycleProcessor(); // 首先将刷新传播到生命周期处理器。 getLifecycleProcessor().onRefresh(); // 推送上下文刷新完毕事件到相应的监听器 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }
总结
至此Spring IOC 初始化和spring bean加载过程就结束.
Spring IOC 初始化: 创建beanFactory
实例对象,创建BeanDefinitionReader
,创建BeanDefinitionScanner
,将ContextAnnotationAutowireCandidateResolver
,ConfigurationClassPostProcessor【bean的扫描和注册】
,CommonAnnotationBeanPostProcessor
,AutowiredAnnotationBeanPostProcessor【@Autowired属性的自动注入】
,PersistenceAnnotationBeanPostProcessor
这5个组件添加到spring容器中。
spring bean加载过程:
- 通过
BeanDefinitionReader
将bean配置类从java_config中读取出来 - 再由
ConfigurationClassPostProcessor
解析配置类 - 通过
BeanDefinitionScanner
扫描配置类中的配置的扫描路径 - 由
ConfigurationClassPostProcessor
包装成beanDefinition,注册到(put)beanDefinitionMap中。 - 最后通过
beanFactory
的getBean
方法将bean实例化.- 在这过程中会调用
registerBeanPostProcessors
方法注册的后置处理器,对bean进行数据填充 AutowiredAnnotationBeanPostProcessor
(处理被@Autowired注解修饰的bean并注入)RequiredAnnotationBeanPostProcessor
(处理被@Required注解修饰的方法)CommonAnnotationBeanPostProcessor
(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等
- 在这过程中会调用