【spring】源码-spring 容器启动过程之 AnnotationConfigWebApplicationContext (四)

目录

AnnotationConfigWebApplicationContext  注解类

register 注册注解类方式

scanner.scan() 扫描类的方式


AnnotationConfigWebApplicationContext  注解类

AnnotationConfigWebApplicationContext  类继承自 AbstractRefreshableWebApplicationContext 类 实现了 AnnotationConfigRegistry 接口,所有此类作用主要是通过注解配置的形式实现对象读取,解析和注册;

//载入注解Bean定义资源
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
		//为容器设置注解Bean定义读取器
		AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
		//为容器设置类路径Bean定义扫描器
		ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

		//获取容器的Bean名称生成器
		BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
		//为注解Bean定义读取器和类路径扫描器设置Bean名称生成器
		if (beanNameGenerator != null) {
			reader.setBeanNameGenerator(beanNameGenerator);
			scanner.setBeanNameGenerator(beanNameGenerator);
			beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
		}

		//获取容器的作用域元信息解析器
		ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
		//为注解Bean定义读取器和类路径扫描器设置作用域元信息解析器
		if (scopeMetadataResolver != null) {
			reader.setScopeMetadataResolver(scopeMetadataResolver);
			scanner.setScopeMetadataResolver(scopeMetadataResolver);
		}
     // 注册自定义注解类到读取器中
		if (!this.annotatedClasses.isEmpty()) {
			if (logger.isInfoEnabled()) {
				logger.info("Registering annotated classes: [" +
						StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]");
			}
			reader.register(this.annotatedClasses.toArray(new Class<?>[this.annotatedClasses.size()]));
		}

		if (!this.basePackages.isEmpty()) {
			if (logger.isInfoEnabled()) {
				logger.info("Scanning base packages: [" +
						StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
			}
			scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()]));
		}

		//获取容器定义的Bean定义资源路径
		String[] configLocations = getConfigLocations();
		//如果定位的Bean定义资源路径不为空
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				try {
					//使用当前容器的类加载器加载定位路径的字节码类文件
					Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
					if (logger.isInfoEnabled()) {
						logger.info("Successfully resolved class for [" + configLocation + "]");
					}
					reader.register(clazz);
				}
				catch (ClassNotFoundException ex) {
					if (logger.isDebugEnabled()) {
						logger.debug("Could not load class for config location [" + configLocation +
								"] - trying package scan. " + ex);
					}
					//如果容器类加载器加载定义路径的Bean定义资源失败
					//则启用容器类路径扫描器扫描给定路径包及其子包中的类
					int count = scanner.scan(configLocation);
					if (logger.isInfoEnabled()) {
						if (count == 0) {
							logger.info("No annotated classes found for specified class/package [" + configLocation + "]");
						}
						else {
							logger.info("Found " + count + " annotated classes in package [" + configLocation + "]");
						}
					}
				}
			}
		}
	}东方鲤鱼

      解析: AnnotationConfigWebApplicationContext  类中实现了loadBeanDefinitions()方法,主要步骤,第一步给容器设置AnnotatedBeanDefinitionReader  读取器和ClassPathBeanDefinitionScanner 扫描器,接着获取bran名称生成器,判断是否为空,不为空就设置给bean定义读取器和bean定义扫描器;第二步 获取容器的作用域元信息解析器ScopeMetadataResolver,并判断是否为空设置,此对象用来解析@Scope注解;第三步判断自定义类是否为空,不为空进行注册 ,此处的reader.register() 方法是将自定义类以bean difinition 形式注册到容器中;第四步 如果自定义包扫描路径不为空注册到扫描器中;第五步 检查容器中资源路径的configLocations 是否为空,循环利用类加载反射拿到配置类 注册到容器中,如果容器类加载器加载定义路径的Bean定义资源失败 ,则启用容器类路径扫描器扫描给定路径包及其子包中的类;

AnnotatedBeanDefinitionReader : 用于 编程式注册 已注解 bean    的 方便适配器,需要提供 BeanDefinitionRegistry 类 构造对象,注册的是 BeanDefinitionRegisty 中 的 beanDefinition;该类 是  ClassPathBeanDefininationScanner 的 一个替代品,使用 相同的 注解策略但是只显示的注册类;
         ClassPathBeanDefininationScanner : 一个 bean 定义的 扫描器 ,用于检查 classpath 下 符合条件的bean ,使用给定的记录器 BeanFactory 或者 ApplicationContext 注册 相关的 bean 定义;符合条件的 类 是 通过 配置 类型过滤器来侦测的,默认的过滤器包括 注解了 Spring 的 Component,Repository,Service,Controller 的 类,而且也支持 Java EE 6 的 ManagedBean 注解 和 JSR-330 的 Named 注解;

getAnnotatedBeanDefinitionReader(beanFactory) 方法 内部涉及的spring 六大后置处理器

org.springframework.context.annotation.internalConfigurationAnnotationProcessor : 内部管理 Configuration 注解处理器 的 bean 的 名称;即ConfigurationClassPostProcessor类;

org.springframework.context.annotation.internalAutowiredAnnotationProcessor:内部管理 Autowired 注解处理器 的 bean 的名称;即AutowiredAnnotationBeanPostProcessor 类;

org.springframework.context.annotation.internalRequiredAnnotationProcessor:内部管理 Required 注解处理器 的 bean 的名称;即RequiredAnnotationBeanPostProcessor
类;

org.springframework.context.annotation.internalCommonAnnotationProcessor:内部管理  JSR-250 注解处理器 的 bean 的名称;即CommonAnnotationBeanPostProcessor 类;

org.springframework.context.annotation.internalPersistenceAnnotationProcessor:内部管理  JPA 注解处理器 的 bean 的名称  , 没有使用 JPA类库,不会加载;即PersistenceAnnotationBeanPostProcessor类;

org.springframework.context.event.internalEventListenerProcessor:内部管理 @EventListener 注解 处理器 的 bean 的名称;即EventListenerMethodProcessor类;

org.springframework.context.event.internalEventListenerFactory:内部管理 EventListenerFactory 的 bean 的名称;即DefaultEventListenerFactory类;
 

register 注册注解类方式

     我们先看读取器的register方法内部 找到doRegisterBean 方法如下

    //Bean定义读取器向容器注册注解Bean定义类
	<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

		//根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(instanceSupplier);
		//========第一步===========================

		//解析注解Bean定义的作用域,若@Scope("prototype"),则Bean为原型类型;
		//若@Scope("singleton"),则Bean为单态类型
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		//为注解Bean定义设置作用域
		abd.setScope(scopeMetadata.getScopeName());
		//为注解Bean定义生成Bean名称
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));


		//========第二步===========================
		//处理注解Bean定义中的通用注解
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
		//主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
		//Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				//如果配置了@Primary注解,设置该Bean为autowiring自动依赖注入装//配时的首选
				if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
				//如果配置了@Lazy注解,则设置该Bean为非延迟初始化,如果没有配置,
				//则该Bean为预实例化
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
				//如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
				//个autowiring自动依赖注入装配限定符,该Bean在进autowiring
				//自动依赖注入装配时,根据名称装配限定符指定的Bean
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}

		//创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		//========第三步===========================
		//根据注解Bean定义类中配置的作用域,创建相应的代理对象
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//========第四步===========================
		//向IOC容器注册注解Bean类定义对象
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}东方鲤鱼

   解析:首先第一步生成注解bean 的定义类 ,接着解析bean的作用域,并设置注解bean作用域和生成bean名称,第二步 使用AnnotationConfigUtils的processCommonDefinitionAnnotations方法处理注解Bean定义类中通用的注解,比如lazy.DependsOn,Description等通用注解,创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据;第三步 根据注解bean 定义对象,生成对应的代理对象,第四步 向ioc容器中注册类定义对象,入参registry 对象就是bean定义注册器;

//将解析的BeanDefinitionHold注册到容器中
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		//获取解析的BeanDefinition的名称
		String beanName = definitionHolder.getBeanName();
		//向IOC容器注册BeanDefinition
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		//如果解析的BeanDefinition有别名,向容器为其注册别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}东方鲤鱼

scanner.scan() 扫描类的方式

   ClassPathBeanDefinitionScanner 类是类路径扫描器,负责扫描解析,注册;

  

//调用类路径Bean定义扫描器入口方法
	public int scan(String... basePackages) {
		//获取容器中已经注册的Bean个数
		int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

		//启动扫描器扫描给定包
		doScan(basePackages);

		// Register annotation config processors, if necessary.
		//注册注解配置(Annotation config)处理器
		if (this.includeAnnotationConfig) {
			AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
		}

		//返回注册的Bean个数
		return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
	}东方鲤鱼

   

//类路径Bean定义扫描器扫描给定包及其子包
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		//创建一个集合,存放扫描到Bean定义的封装类
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		//遍历扫描所有给定的包
		for (String basePackage : basePackages) {
			//调用父类ClassPathScanningCandidateComponentProvider的方法
			//扫描给定类路径,获取符合条件的Bean定义
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			//遍历扫描到的Bean
			for (BeanDefinition candidate : candidates) {
				//获取Bean定义类中@Scope注解的值,即获取Bean的作用域
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				//为Bean设置注解配置的作用域
				candidate.setScope(scopeMetadata.getScopeName());
				//为Bean生成名称
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				//如果扫描到的Bean不是Spring的注解Bean,则为Bean设置默认值,
				//设置Bean的自动依赖注入装配属性等
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				//如果扫描到的Bean是Spring的注解Bean,则处理其通用的Spring注解
				if (candidate instanceof AnnotatedBeanDefinition) {
					//处理注解Bean中通用的注解,在分析注解Bean定义类读取器时已经分析过
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				//根据Bean名称检查指定的Bean是否需要在容器中注册,或者在容器中冲突
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					//根据注解中配置的作用域,为Bean应用相应的代理模式
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					//向容器注册扫描到的Bean
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}东方鲤鱼

  解析:对上下文中的配置通过类路径扫描器扫描到放到一个set 集合,循环这些类定义,对其作用域元数据进行判断,生成bean定义名称,然后设置自动注入的属性,如果扫描的不是注解bean 定义的类 设置默认值,如果是扫描类,则和上边注册的方式一样,解析通用注解;然后根据代理模式 创建代理完成向容器的注册;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方鲤鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值