接着上一节,我们已经把配置类中的所有信息都解析出来,放到了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 method
beanDef.setBeanClassName(configClass.getMetadata().getClassName());
beanDef.setFactoryMethodName(methodName);
}
else {
// instance @Bean method
beanDef.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 well
readerClass = XmlBeanDefinitionReader.class;
}
}
BeanDefinitionReader reader = readerInstanceCache.get(readerClass);
if (reader == null) {
try {
// Instantiate the specified BeanDefinitionReader
reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry);
// Delegate the current ResourceLoader to it if possible
if (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)) { //新的Bean
BeanDefinition 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());