接着上一节,我们已经把配置类中的所有信息都解析出来,放到了configClass中,现在我们调用loadBeanDefinition()方法,注解解析出来的bean。
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) { //创建配置类 bean 定义 读取器this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);//【加载】bean定义
alreadyParsed.addAll(configClasses); //添加到已解析的集合中
调用reader,注解方式使用的是ConfigurationClassBeanDefinitionReader类,而xml方式使用的是DefaultBeanDefinitionReader。
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();for (ConfigurationClass configClass : configurationModel) {loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); //【入】}
}
遍历一个一个处理configClass,我们实验demo中只配置了一个配置类,所以这里只有一个configClass
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {if (trackedConditionEvaluator.shouldSkip(configClass)) {String beanName = configClass.getBeanName();if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {this.registry.removeBeanDefinition(beanName);}this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());return;}if (configClass.isImported()) { //是否是@import进来的registerBeanDefinitionForImportedConfigurationClass(configClass);}for (BeanMethod beanMethod : configClass.getBeanMethods()) { //处理@Bean注解方法loadBeanDefinitionsForBeanMethod(beanMethod); //一个一个方法处理}//处理@importResource资源loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());//处理 ImportBeanDefinitionRegister接口的实现类,比如aop中的loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
找到了处理configClass的地方,这里分为了4个处理方式,分别对应了@import,@Bean,@ImportResources,ImportBeanDefinitionRegister接口的实现类,第二中是很普通的,而第四种用在了aop的开启注解中使用,接下来我们直接看最常用的:
1.Bean
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {ConfigurationClass configClass = beanMethod.getConfigurationClass();MethodMetadata metadata = beanMethod.getMetadata();String methodName = metadata.getMethodName();//是否跳过if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {configClass.skippedBeanMethods.add(methodName);return;}if (configClass.skippedBeanMethods.contains(methodName)) {return;}//找到@Bean注解的属性信息 具有5个属性AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);//名字处理List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));String beanName = (!names.isEmpty() ? names.remove(0) : methodName);for (String alias : names) {this.registry.registerAlias(beanName, alias);}//beanDefinition 封装ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);beanDef.setResource(configClass.getResource());beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));//各种注解处理:Autowire,initMethod,。。也就是@Bean自带五个属性,进行处理if (metadata.isStatic()) {// static @Bean methodbeanDef.setBeanClassName(configClass.getMetadata().getClassName());beanDef.setFactoryMethodName(methodName);}else {// instance @Bean methodbeanDef.setFactoryBeanName(configClass.getBeanName());beanDef.setUniqueFactoryMethodName(methodName);}beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);Autowire autowire = bean.getEnum("autowire");if (autowire.isAutowire()) {beanDef.setAutowireMode(autowire.value());}String initMethodName = bean.getString("initMethod");if (StringUtils.hasText(initMethodName)) {beanDef.setInitMethodName(initMethodName);}String destroyMethodName = bean.getString("destroyMethod");beanDef.setDestroyMethodName(destroyMethodName);
....//注册到BeanFactory中,作为BeanDefinition保存在集合中this.registry.registerBeanDefinition(beanName, beanDefToRegister); //注册
}
解析完毕之后,就注册到DefaultBeanFactory中,等待被实例化,实例化是在refresh()方法的第十一步中,实例化单例非懒加载的bean。
2.@ImposrResource
资源处理,使用资源读取器,
private void loadBeanDefinitionsFromImportedResources(Map<String, Class<? extends BeanDefinitionReader>> importedResources) {Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>();importedResources.forEach((resource, readerClass) -> {// Default reader selection necessary?if (BeanDefinitionReader.class == readerClass) {if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) {// When clearly asking for Groovy, that's what they'll get...readerClass = GroovyBeanDefinitionReader.class;}else {// Primarily ".xml" files but for any other extension as wellreaderClass = XmlBeanDefinitionReader.class;}}BeanDefinitionReader reader = readerInstanceCache.get(readerClass);if (reader == null) {try {// Instantiate the specified BeanDefinitionReaderreader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);// Delegate the current ResourceLoader to it if possibleif (reader instanceof AbstractBeanDefinitionReader) {AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader);abdr.setResourceLoader(this.resourceLoader);abdr.setEnvironment(this.environment);}readerInstanceCache.put(readerClass, reader);}}reader.loadBeanDefinitions(resource); //使用xml的加载方式进行解析});
}
3.加载接口实现类
处理方式比较简单,直接把该接口的唯一方法,执行就可以了。
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {registrars.forEach((registrar, metadata) ->registrar.registerBeanDefinitions(metadata, this.registry)); //调用方法实现
}
回到ConfigurationClassPostProcessor类中,加载完毕之后,保存configClasses,然后在beanFactory中,找出新加入的beanDefinition再一次进行解析,递归解析:
candidates.clear(); //处理完,一次清空//现在的bean 大于了最开始的bean数量,进入if (registry.getBeanDefinitionCount() > candidateNames.length) {String[] newCandidateNames = registry.getBeanDefinitionNames(); //获得新的beanNames 集合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)) { //新的BeanBeanDefinition bd = registry.getBeanDefinition(candidateName);if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&!alreadyParsedClasses.contains(bd.getBeanClassName())) {candidates.add(new BeanDefinitionHolder(bd, candidateName)); //封城成为xxholder保存,这样就存在一种循环遍历}}}candidateNames = newCandidateNames;}
}
while (!candidates.isEmpty());