spring-源码-AnnotationConfigApplicationContext-创建分析-4

前言

本篇章仅仅就讲一个方法的调用流程,这里当然还是涉及到了其他知识点,建议先看一下

  1. ApplicationContext-2
  2. AnnotationMetadata 注解元数据
  3. BeanDefinition

register

用于注册我们的启动类,简单来说其实就是用于注册 带有@ComponentScan 注解的 目标类,当然不带也无所谓,只是简简单单注册一个Bean而已,但是这个方法的主要作用其实还是 为了注册 一个目标类,

代码分析

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    //主要分析这段代码
    register(componentClasses);
}

调用register()

看到这里我们可以清晰的了解到 其实还是委托为 AnnotatedBeanDefinitionReader 去做了

@Override
public void register(Class<?>... componentClasses) {
    this.reader.register(componentClasses);
}

调用register()

this.reader指的我们最开始创建的AnnotatedBeanDefinitionReader对象

public void register(Class<?>... componentClasses) {
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}
 
public void registerBean(Class<?> beanClass) {
    doRegisterBean(beanClass, null, null, null, null);
 
}

调用doRegisterBean()

  1. 传递了我们扫描的Class
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
                                @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
                                @Nullable BeanDefinitionCustomizer[] customizers) {
    
    // 将Bean配置类信息转成容器中 AnnotatedGenericBeanDefinition 数据结构,
    // AnnotatedGenericBeanDefinition 继承自 BeanDefinition 作用是定义一个bean的数据结构,
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    	
    // getMetadata可以获取到该bean上的元数据
    // @Conditional  装配条件判断是否需要跳过注册,如果是跳过注册则不会将当前Bean注入到Spring容器中
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }
    //在初始化的时候为Null
    abd.setInstanceSupplier(supplier);
    
    //解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    
    //生成bean配置类beanName
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    
    //通用注解解析到 abd 结构中,主要是处理 Lazy, primary DependsOn, Role ,Description 这五个注解
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    
    // @Qualifier 特殊限定符处理,
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                // 如果配置@Primary注解,则设置当前 Bean为 自动装配 autowire 时首选bean
                abd.setPrimary(true);
            } else if (Lazy.class == qualifier) {
                //设置当前bean为延迟加载
                abd.setLazyInit(true);
            } else {
                //其他注解,则添加到abd结构中
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    //初始化是不会走这个方法的
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            //自定义bean添加到BeanDefinition
            customizer.customize(abd);
        }
    }
    //这类:简单理解就是将 AnnotatedGenericBeanDefinition 和beanName 做一个映射
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
 
    //创建代理对象
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
 
    // 用于保存注bean定义信息(beanname 和 beandefine映射)
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
 

判断是否需要跳过-shouldSkip()

  1. shouldSkip()
  2. shouldSkip()
    public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {

        // 如果元数据是一个 null 或者 不存在 @Conditional 注解
        if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
            return false;
        }
		// 第一次进来本来就是NUll~~
        if (phase == null) {
            // 判断 matadata
            // 并且 是特定注解
            if (metadata instanceof AnnotationMetadata &&
            		// 判断不是接口 是一些特定的注解 或者 包含了 @Bean注解的 方法的
                    ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
                // @Configuration 配置类的处理
                return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
            }
            // 只有 @Conditional 注解的处理
            return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
        }

        // 要解析的配置类的条件集合
        List<Condition> conditions = new ArrayList<>();

        //获取 @Conditional 注解的里面的所有 条件类全限定类名
        for (String[] conditionClasses : getConditionClasses(metadata)) {
            for (String conditionClass : conditionClasses) {
                //  获取条件对象,这里可以理解为 @Conditional({A.class}) 这个A 类型的 对象,由于我们的A类实现了 Condition 这个接口,所以在上传直接进行了强转
                Condition condition = getCondition(conditionClass, this.context.getClassLoader());
                //添加到集合当中去
                conditions.add(condition);
            }
        }
        // 排序
        AnnotationAwareOrderComparator.sort(conditions);

        //	遍历conditions,进行判断
        for (Condition condition : conditions) {
            ConfigurationPhase requiredPhase = null;
            // 判断是不是实现了这个接口的 这个接口 比  Condition 更加高级一点
            if (condition instanceof ConfigurationCondition) {
                //  执行这个方法
                requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
            }
            //阶段不满足条件的话,返回true并跳过这个bean的解析
            if ((requiredPhase == null || requiredPhase == phase) &&
                    // 去执行控制的方法,如果返回的 true 则代表可以创建,如果返回 false 认为不可以创建
                    // 不可以创建 结果取反 !false 就是 true
                    !condition.matches(this.context, metadata)) {
                //  返回 true 不进行创建
                return true;
            }
        }

        return false;
    }

解析Scope元数据-resolveScopeMetadata()

	public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
	    //创建一个 @Scope 注解的元数据
		ScopeMetadata metadata = new ScopeMetadata();
		//判断是不是 这个类型,在初始化的时候 已经将我们的对象转成了 AnnotatedBeanDefinition 类型
		if (definition instanceof AnnotatedBeanDefinition) {
			AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
			//这里是去解析注解去了
			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
			// 属性不为 null
			if (attributes != null) {
			    //获取其 @Scope.value 属性
				metadata.setScopeName(attributes.getString("value"));
                //获取其 @Scope.proxyMode 属性
				ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
				// 如果 @Scope.proxyMode == 默认值的话
				if (proxyMode == ScopedProxyMode.DEFAULT) {
				    //将其设置为  ScopedProxyMode.NO  这个值是在构造函数创建的~~
					proxyMode = this.defaultProxyMode;
				}
				metadata.setScopedProxyMode(proxyMode);
			}
		}
		return metadata;
	}

调用registerBeanDefinition()

public static void registerBeanDefinition(
    BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    throws BeanDefinitionStoreException {
 
    //获取BeanName
    String beanName = definitionHolder.getBeanName();
    //注册到spring容器中,这个方法我们在注册 后置处理器的时候已经分析过了
    //1. name 和 BeanDefinition  放到 beanDefinitionMap中
    //2. name 存到 beanDefinitionNames 中
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
 
    //获取Bean的别名
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

springboot

springboot 最终也是调用大致的流程,只贴前置流程的源码

调用流程

项目启动

@SpringBootApplication
public class SpringIocApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringIocApplication.class, args);
    }
}

调用run方法

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
	return run(new Class<?>[] { primarySource }, args);
}
  • 内部调用 run 方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
	return new SpringApplication(primarySources).run(args);
}
  • 创建对象
public SpringApplication(Class<?>... primarySources) {
	this(null, primarySources);
}
public SpringApplication(
	ResourceLoader resourceLoader, 
	Class<?>... primarySources) {
		
	// 将 我们的 启动类,放到集合中 然后设置给  primarySources 这个属性
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	
}
  • 然后调用run 方法
public ConfigurableApplicationContext run(String... args) {
	prepareContext(context, environment, listeners, applicationArguments, printedBanner);
}

剩余流程

剩余流程就不贴代码了,自己可以跟一下,为啥上面贴呢,主要是将 将启动类放到 primarySources 集合中

  1. 调用 prepareContext 方法

    1. 调用 getAllSources 方法 获取 启动类集合~~
  2. 调用 load()

  3. 调用 load()

  4. 调用 load()

  5. 调用 load()

  6. 调用 annotatedReader.register(source);

  7. 循环调用 registerBean()

  8. 调用 doRegisterBean()

扩展阅读

通过源码分析,我们传递的扫描类,最终将我们的Bean,处理完成后放进了beanDefinitionMapbeanDefinitionNames

不依托AnnotationConfigApplicationContext 单独调用这个方法看看,

public class RegisterContext {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        AnnotatedBeanDefinitionReader definitionReader = new AnnotatedBeanDefinitionReader(beanFactory);
        definitionReader.register(User.class);
        User bean = beanFactory.getBean(User.class);
        System.out.println(bean);
    }
}

@Conditional(Person.class)
class User {
}

//用于控制 User 是否注册
class Person implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 返回 true 就会注入,返回 false 就不会注册 User 这个Bean,如果没注册在获取的时候会出现问题...
        return false;
    }
}

流程图

  • 从流程图上看, 最终 register 的调用由 AnnotatedBeanDefinitionReader 调用
    在这里插入图片描述

后续文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值