Spring源码之Bean的注册(注解方式)

1.创建AnnotationConfigApplicationContext

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.eragon");

这里传的参数是包名,spring会自动扫描该包下所有的类,对bean进行配置。

public AnnotationConfigApplicationContext(String... basePackages) {
		// 初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
		this();
		// 对包进行扫描
		scan(basePackages);
		// 刷新容器
		refresh();
	}

我们先来看scan(basePackages),对包下所有类的扫描

public void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		this.scanner.scan(basePackages);
	}
public int scan(String... basePackages) {
		// 当前容器已注册的bean的个数
		int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
		
		// 真正扫描包的方法
		doScan(basePackages);

		// Register annotation config processors, if necessary.
		if (this.includeAnnotationConfig) {
			AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
		}

		return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
	}

doScan(basePackages):

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		// 断言,package至少有一个
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		// 使用BeanDefinitionHolder封装
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {

			// 获得所有需要注册的bean(主要是使用了@Compoment注解的类)
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

			// 注册bean
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				// 设置scope
				candidate.setScope(scopeMetadata.getScopeName());
				// 获得beanName
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					/**
					 * 处理@Autowire当能找到多个类时的问题,会根据scan.setAutowireCandidatePatterns
					 * 设置的匹配规则查找对应的bean
					 */
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					/**
					 * BeanDefinition设置一些常规的属性,比如lazy,role等,
					 */
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				// 校验beanName必须唯一
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);

					/**
					 * 是否需要代理,分为cglib和jdk两种动态代理方式
					 */
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					/**
					 * 注册beanDefinition到容器中
					 */
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

registerBeanDefinition()在xml的注册中已经跟踪过,就是把beanDefinition放到容器里,这里省略。

总结:

通过注解方式的注册Bean和XML基本逻辑都是一样,先解析再注册,我们发现从源码层面通过注解的方式配置Bean比XML方式简洁的多,所以Spring也推荐使用注解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值