曾彪彪的个人网站
首页
文章列表
>>
文章详情
Spring IoC源码分析(注解版) -- 中
作者:
曾彪彪
日期:
2023-05-16 05:20:23
阅读(1117)
分类:
Spring 家族
上一篇文章[Spring IoC源码分析(注解版) -- 上](<https://zengbiaobiao.com/article/detail/26>) 分析了Spring IoC容器中关于BeanDefinition的registy过程。我们接着来分析剩下的内容。 ### 加载BeanDefinition 上一篇我们分析完了AnnotationConfigApplicationContext类中的register方法,现在来分析refresh方法。refresh其实是在AbstractApplicationContext类中实现的。AbstractApplicationContext实现了BeanDefinitionRegistry以及BeanFactory的大部分功能,所以其子类如AnnotationConfigApplicationContext或ClassPathXmlApplicationContext只需要实现部分相关功能(如加载resource)即可。 我们来看refresh方法的代码: ```java public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 设置一些属性值,如开始日期等,不是重点 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // 获取beanFactory,对于AnnotationConfigApplicationContext而言,其实在其父类GenericApplicationContext的构造函数中就已经创建好了,beanFactory是DefaultListableBeanFactory类的一个实例。 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 配置一些必要的对象,如ClassLoader,也不是重点。 prepareBeanFactory(beanFactory); try { // BeanFactory后置处理器回调函数,让子类有机会在创建beanFactory之后,有机会对beanFactory做额外处理。模板方法模式的使用。 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 调用BeanFactoryPostProcessor的postProcessBeanFactory方法。 // Spring提供了BeanFactoryPostProcessor接口,用于对BeanFactory进行扩展。如果一个Bean实现了BeanFactoryPostProcessor接口的话,在这里会调用其接口方法。 // 这个方法和上一个方法的区别在于,上一个方法是调用ApplicationContext子类的postProcessBeanFactory方法,而这个方法是调用所有BeanFactoryPostProcessor实例的postProcessBeanFactory方法。这个方法做了很多事情,是我们要重点分析的对象。 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 只是注册BeanPostProcessor,还没调用后置处理器相关的方法。如果Bean实现了BeanPostProcessor接口的话,在这里注册其后置处理器。 // BeanPostProcessor也是Spring提供的另一个有用接口,所有的BeanPostProcessor会被添加到Spring容器列表中。在应用Bean被实例化前后,Spring会一次调用BeanPostProcessor列表中的接口方法。后边会有具体分析。 // 所有实现了BeanFactoryPostProcessor和BeanPostProcessor接口的Bean,理论上是提供给Spring使用的,我们叫他功能性Bean。而其它Bean,如UserService,叫应用型Bean。 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 国际化的东西,不是重点。 initMessageSource(); // Initialize event multicaster for this context. // 我们现在不讨论事件机制,主要关注Bean的加载和创建过程,所以跳过。 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 好吧,又来一个回调方法,模板方法模式哟。 onRefresh(); // Check for listener beans and register them. // 不讨论事件机制,跳过。 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // 这又是一个重点方法。这个方法会实例化所有非lazy-init的singleton bean,并执行与Spring Bean生命周期相关的方法。如init-method,*aware接口方法等。 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // 与事件有关,跳过 finishRefresh(); } } } ``` refresh方法中执行了许多方法,但其实我们如果想了解Bean加载及创建,只要关注3个即可,他们是。 ```java invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); finishBeanFactoryInitialization(beanFactory); ``` 现在来一一分析分析,先看invokeBeanFactoryPostProcessors。 ```java protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 委托给PostProcessorRegistrationDelegate执行,调用以下方法 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // 省略其它 } } ``` 再来看PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法 ```java public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { if (beanFactory instanceof BeanDefinitionRegistry) { List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // 先处理BeanDefinitionRegistryPostProcessor,并调用其postProcessBeanDefinitionRegistry方法。 // BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的一个子接口,它允许注册更多的BeanDefinition。我们之前讲过,前面的register方法中,只注册了配置类(添加了@Configuration的类),其它类的BeabnDifination还没有被注册进来 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { // 这里会得到一个ConfigurationClassPostProcessor类,这个类的作用很明显,就是要继续注册配置类中要求注册的BeanDefination,如在配置类上添加了@ComponentScan注解,那么会进行包扫描,指定包下的所有添加了@Component,@Service等注解的类全部注册进来。 // 那么这个类是什么时候注册的呢,我们稍后会讲。 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); // 在这里开始调用BeanDefinitionRegistryPostProcessor的后置处理器postProcessBeanDefinitionRegistry方法。 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // 省略大量重复代码,主要处理各种优先级的BeanFactoryPostProcessor对象。可以为BeanFactoryPostProcessor设置优先级,优先级高的对象会先被调用。 // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // 对所有的postProcessor进行分类,高优先级的和正常优先级的分别放在不同的列表中,高优先级的先调用其postProcessBeanFactory方法。 List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // 此处省略重复调用代码,就是对高优先级的BeanFactoryPostProcessor先执行invokeBeanFactoryPostProcessors方法,然后是低优先级,再之后是无优先级的 List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { // 这里这行代码,它调用了beanFactory.getBean方法。我们知道只要调用了getBean方法,如果Bean没有被加载,Spring就会创建该Bean,并对其进行相关属性复制。所以对于实现了BeanFactoryPostProcessor的Bean,在这里就已经进行实例化了。因为它要拿到当前对象,才能执行其接口方法。 nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } // 开始进行回调。 invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); beanFactory.clearMetadataCache(); } ``` 我们来介绍一下BeanFactoryPostProcessor接口,它叫BeanFactory后置处理器。如果你的类实现了这个接口,那么在BeanFactory创建完成之后,Spring会调用这个类的postProcessBeanFactory方法。这个类为用户提供了扩展BeanFactory的机会。 接下来要说的东西很多,我们首先要讲ConfigurationClassPostProcessor是怎么注册进来的,然后再分析ConfigurationClassPostProcessor的processConfigBeanDefinitions代码,最后分析invokeBeanFactoryPostProcessors方法。 先来看ConfigurationClassPostProcessor的注册过程。回到最初AnnotationConfigApplicationContext的构造函数中。 ```java public AnnotationConfigApplicationContext() { // 创建了一个AnnotatedBeanDefinitionReader对象,ConfigurationClassPostProcessor这个类就是在这里注入的。 this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } ``` 我们继续往下看AnnotatedBeanDefinitionReader的构造函数。 ```java public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, getOrCreateEnvironment(registry)); } public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); // 注册注解配置类的处理器。 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } ``` 进入AnnotationConfigUtils.registerAnnotationConfigProcessors方法。 ```java public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) { // 调用了registerAnnotationConfigProcessors方法 registerAnnotationConfigProcessors(registry, null); } public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { // 看见没有,在这里注册了ConfigurationClassPostProcessor类。 RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); // 主要是调用了registerPostProcessor来进行注册的。 beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); // 同时也注册了另一个重要类AutowiredAnnotationBeanPostProcessor beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 其它代码就不看了。省略... return beanDefs; } ``` 简单看一下registerPostProcessor,就是调用registerBeanDefinition注册一个BeanDefination。不往下看了,前面register里讲到过。 ```java private static BeanDefinitionHolder registerPostProcessor( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) { definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(beanName, definition); return new BeanDefinitionHolder(definition, beanName); } ``` 现在ConfigurationClassPostProcessor的注册过程弄明白了。我们接着看下一段代码分析,调用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法。ConfigurationClassPostProcessor这个类是Spring帮我们注册进来,其作用是用于注册用户自定义的类。看源代码: ```java // 接着PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors的代码分析,会调用以下方法 private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { // 这里的postProcessor就是ConfigurationClassPostProcessor postProcessor.postProcessBeanDefinitionRegistry(registry); } } ``` 进入ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法。 ```java public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { // 开始注册Config类中定义的BeanDefinition processConfigBeanDefinitions(registry); } ``` ```java public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); String[] candidateNames = registry.getBeanDefinitionNames(); // 将配置类放在configCandidates列表中。代码省略... // 创建配置类的分析器,对配置类进行分析。配置类就是我们添加了@Configuration注解的类,可以有多个的。我写的demo中只有一个,叫SpringConfig。 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); do { // 开始分析配置类 parser.parse(candidates); parser.validate(); // 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); } while (!candidates.isEmpty()); } ``` 上面方法中,我们需要分析两个方法parser.parse(candidates)和this.reader.loadBeanDefinitions(configClasses)。先来看第一个方法: ```java public void parse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { // 调用链往下看 parse(bd.getBeanClassName(), holder.getBeanName()); } this.deferredImportSelectorHandler.process(); } protected final void parse(Class<?> clazz, String beanName) throws IOException { // 继续往下看 processConfigurationClass(new ConfigurationClass(clazz, beanName)); } protected void processConfigurationClass(ConfigurationClass configClass) throws IOException { // Recursively process the configuration class and its superclass hierarchy. SourceClass sourceClass = asSourceClass(configClass); do { // 最终调到了这个方法,处理配置类 sourceClass = doProcessConfigurationClass(configClass, sourceClass); } while (sourceClass != null); this.configurationClasses.put(configClass, configClass); } ``` 通过一些列调用,最终调用到了doProcessConfigurationClass方法。 ```java protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { // 这两个方法简单过,就是处理配置类里边的内部类和@PropertySource注解 processMemberClasses(configClass, sourceClass); processPropertySource(propertySource); // 处理 @ComponentScan 注解类,重点,先获取加了@ComponentScan注解的配置类 Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately // 开始扫描指定package下的所有Bean,那些加了@Component,@Service,@Repository等注解的类,都会加进来。 Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { // 如果扫描到了配置类,则递归处理,继续分析配置类。 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { // 这个方法我们就不分析了,递归哈 parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // Process any @Import annotations processImports(configClass, sourceClass, getImports(sourceClass), true); // Process individual @Bean methods // 将所有都添加了@Bean注解的方法添加到configClass中,这里没有注册,仅仅只是添加。后边有一个叫reader.loadBeanDefinitions的方法来处理它。 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces processInterfaces(configClass, sourceClass); // No superclass -> processing is complete return null; } ``` 上面的方法中,我们来看componentScanParser.parse方法,看是怎样扫描包并且注册BeanDefinition的。 ```java public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { // 创建scanner ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); Set<String> basePackages = new LinkedHashSet<>(); // 添加所有的package,代码省略... // 开始扫描 return scanner.doScan(StringUtils.toStringArray(basePackages)); } ``` 我们接下来看scanner.doScan ```java protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); for (String basePackage : basePackages) { // 找出当前包下面的所有符合条件的类,这个方法我们就不分析了。 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) { // 处理一些其他情况,也不说了... if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); // 最后注册BeanDefinition,这样就将包下的所有BeanDefintion都注册完成了 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; } ``` 到这里为止,我们配置类的分析就结束了,将所有的包下的BeanDefinition都注册完成了。讲了这么多,我们还记得是从哪个方法进来的吗?是从这个ConfigurationClassPostProcessor的processConfigBeanDefinitions方法进来的,再回到这个方法。 ```java public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); String[] candidateNames = registry.getBeanDefinitionNames(); ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); do { // 刚才是在这里一下向下分析的。 parser.parse(candidates); parser.validate(); // 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); } while (!candidates.isEmpty()); } ``` 现在我们来分析reader.loadBeanDefinitions方法。 ```java private void loadBeanDefinitionsForConfigurationClass( ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) { // 处理Imported的配置类 if (configClass.isImported()) { registerBeanDefinitionForImportedConfigurationClass(configClass); } for (BeanMethod beanMethod : configClass.getBeanMethods()) { // 注册所有的@Bean方法上的类,重点看一下这个方法 loadBeanDefinitionsForBeanMethod(beanMethod); } // 处理其它注解,这里就不分析了。 loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); } ``` 看看loadBeanDefinitionsForBeanMethod这个方法 ```java private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { ConfigurationClass configClass = beanMethod.getConfigurationClass(); // 一些别名处理的代码都省略了... // 创建BeanDefinition ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata); // 处理initMethod和destroyMethod String initMethodName = bean.getString("initMethod"); if (StringUtils.hasText(initMethodName)) { beanDef.setInitMethodName(initMethodName); } String destroyMethodName = bean.getString("destroyMethod"); beanDef.setDestroyMethodName(destroyMethodName); // Replace the original bean definition with the target one, if necessary BeanDefinition beanDefToRegister = beanDef; // 最后注册这个BeanDefinition this.registry.registerBeanDefinition(beanName, beanDefToRegister); } ``` 现在,所有加了@Bean注解的方法定义的BeanDefinition也都被注册了。 ### 总结 讲到这里,感觉说了好多,还记得从哪里进来的吗,对,是从invokeBeanDefinitionRegistryPostProcessors这个方法。今天讲的还挺多的,在继续之前,我们先回顾一下今天讲的知识。 AnnotationConfigApplicationContext构造函数中会创建一个AnnotatedBeanDefinitionReader实例,用于读取基于注解的BeanDefinition。在这个Reader创建过程中,会注册ConfigurationClassPostProcessor类,ConfigurationClassPostProcessor负责加载配置类中的BeanDefinition。 之后调用register和refresh方法。 register方法中注册配置类的BeanDefinition。 refresh方法中包含一系列方法,其中也包含一些扩展方法,是基于模板方法模式的,如postProcessBeanFactory,但我们主要关注的是下边3个。 ```java invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); finishBeanFactoryInitialization(beanFactory); ``` invokeBeanFactoryPostProcessors负责调用BeanFactory的后置处理方法,所有实现了BeanFactoryPostProcessor接口的Bean,在这个阶段都会调用其postProcessBeanFactory。 Spring提供了一个重要的类ConfigurationClassPostProcessor,在这个阶段被调用,目的是分析并扫描配置类要求注入的类,并为这些类注册BeanDefinition。 BeanFactoryPostProcessor是Spring提供的用于扩展BeanFactory的接口。用户可以自定义一些类并实现这个接口,这样在IoC容器初始化的过程中,这些BeanFactoryPostProcessor对象的接口方法会被执行。 --- 所有文章在[Github](<https://github.com/zengbiaobiao>)上同步,你也可以访问我的[个人博客](http://zengbiaobiao.com)点击查看
评论(0)
评论(必填)
名称(必填)
联系方式(可选)
验证码(必填)
提交
评论(必填)
名称(必填)
联系方式(可选)
验证码(必填)