Spring基于注解的Ioc容器源码分析01|周末学习

513 阅读5分钟

「本文已参与 周末学习计划,点击查看详情 」

Spring从2.5开始支持基于注解的bean扫描,考虑到目前流行的SpringBoot框架也是大量采用了注解驱动开发,所以本文直接跨过xml配置,从注解驱动开始,一探究竟为什么加了@Service,就可以直接在Spring中注入并调用方法了?

Spring源码系列所有的源码都可以在我个人的Github仓库下载。

准备调试环境

基于上一篇文章的源码编译环境,我们新建了一个spring-learn模块,接下来就在这个模块里搞点事情。

UserService.java & UserServiceImpl.java

public interface UserService {
	public String getUserName(String userId);
}
public class UserServiceImpl implements UserService {
	@Override
	public String getUserName(String userId) {
		return userId.toUpperCase();
	}
}

AnnotationConfig.java

@Configuration
public class AnnotationConfig {
	@Bean
	public UserService userServiceImpl(){
		return new UserServiceImpl();
	}
}

AnnotationContextMain.java

/**
 * @description: 基于注解的Spring Ioc容器
 * @author: Poppy
 * @create: 2021-05-19 16:16
 **/
public class AnnotationContextMain {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.poppy.ioc");
		UserService userService = context.getBean(UserService.class);
		System.out.println(userService.getUserName("poppy"));
	}
}

执行main()方法,输出的结果POPPY,从代码上看,无非就是new了一个AnnotationConfigApplicationContext,然后从这个Conntext中拿到了UserService的实例,并调用了getUserName()方法。接下来重点看下AnnotationConfigApplicationContext()的构造方法。

        /**
	 * Create a new AnnotationConfigApplicationContext, scanning for bean definitions
	 * in the given packages and automatically refreshing the context.
	 * @param basePackages the packages to check for annotated classes
	 */
	public AnnotationConfigApplicationContext(String... basePackages) {
                //01 调用父类的无参构造函数,调用初始化方法
		this();
                //02 扫描指定路径下面的BeanDefinition
		scan(basePackages);
                //03 完成整个容器的刷新(实例化,BeanPostProsser等)
		refresh();
	}

这三个方法就是整个容器的创建启动过程了,接下来分为3大块来分析具体的流程。

01初始化AnnotationConfigApplicationContext

1.init()

    public AnnotationConfigApplicationContext() {
                //调用父类无参的构建函数new出一个DefaultListableFactory
		/**
		 * 1.1初始化基于注解的beanDefinition扫描器
		 * 把处理注解的bean定义 放入到容器中
		 */
		this.reader = new AnnotatedBeanDefinitionReader(this);
		//1.2初始化 基于classpath的beanDefinition扫描器 默认使用的是这个
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

1.1 主要完成 初始化注解后处理器 到BeanDefinitionMap中

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		//传递过来的 AnnotationConfigApplicationContext bean定义 容器
		this.registry = registry;
		/**
		 * 用于计算判断 {@link Conditional} 注解
		 */
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		/**
		 * 1.1.1注册 所相关注解的后置处理器 到registry
		 */
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

1.1.1 org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)

if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			/**
			 * 注册处理 {@link Configuration} 后置处理器
			 */
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			/**
			 * 注册处理 {@link Autowired} 后置处理器
			 */
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			/**
			 * 注册处理 {@link Required} 后置处理器
			 */
			beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			//@EventListener
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}

1.2 初始化基于指定路径的包扫描器

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		this.registry = registry;

		if (useDefaultFilters) {
			// 初始化默认的包扫描过滤器,主要是 3类注解扫描
			registerDefaultFilters();
		}
		setEnvironment(environment);
		//设置资源加载器
		setResourceLoader(resourceLoader);
	}

注册默认的IncludeFilter,后面会用来筛选符合条件的bean registerDefaultFilters()

protected void registerDefaultFilters() {
		//加入扫描@Component注解的过滤器,这样就能扫到 @Component注解 以及其派生注解 @Controller,@Service,Repository...
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
		ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
		try {
			//JSR-250规范的注解
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
			logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
		}
		catch (ClassNotFoundException ex) {
			// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
		}
		try {
			//JSR-330规范的注解
			this.includeFilters.add(new AnnotationTypeFilter(
					((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
			logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

到此完成了BeanFactory,注解后处理PostProcessorAnnotationTypeFilter初始化。

02扫描所有的BeanDefinition

public void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		// 使用刚刚基于指定路径的 ClassPathBeanDefinitionScanner 扫描包
		this.scanner.scan(basePackages);
	}
	public int scan(String... basePackages) {
		int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

		/**
		 * 扫描 所有的 被@Component以及派生注解修饰的 beanDefinition (注意还没有生成bean)
		 * 判断一个类的时候 可以指定父类或者接口
		 */
		doScan(basePackages);

		// Register annotation config processors, if necessary.
		// 在上面初始AnnotatedBeanDefinitionReader 已经处理过了
		if (this.includeAnnotationConfig) {
			/**
			 * @link org.springframework.context.annotation.AnnotatedBeanDefinitionReader.AnnotatedBeanDefinitionReader(org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.core.env.Environment)
			 */
			AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
		}

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

doSacn()

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
			/**
			 * 【重要】
			 * 2.1通过Resource查找类路径下面候选的类
			 * 2.2.做一些基础的处理
			 * 2.3.把处理完成的BeanDefinition注册到BeanFactory
			 * 2.4.完成所有的类扫描
			 */
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				//绑定BeanDefinition与Scope
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				//查看是否配置类是否指定bean的名称,如没指定则使用类名首字母小写
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				//2.2 处理lazy、Autowire、DependencyOn、initMethod、enforceInitMethod、destroyMethod、enforceDestroyMethod、Primary、Role、Description这些逻辑的
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				// 检查BeanDefinition是否存在:初次扫描到的肯定是不存在的
				if (checkCandidate(beanName, candidate)) {
					// 用BeanDefinitionHolder再次包装BeanDefinition
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					//检查scope是否创建,如未创建则进行创建
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					//2.3 注册BeanDefinition到BeanFactory的BeanDefinitionMap中。
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		//2.4
		return beanDefinitions;
	}

2.1 扫描包findCandidateComponents()

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			//2.1.1组装扫描路径
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			//2.1.2扫描指定路径下面的所有类
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				if (resource.isReadable()) {
					try {
						/**
						 * 2.1.3元数据阅读器,获取类上的资源,类信息,注解信息
						 */
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						/**
						 * 2.1.4【重要】 直接判断是否是需要装配的Bean组件
						 * 是:放入集合统一返回
						 * 否:过滤
						 */
						if (isCandidateComponent(metadataReader)) {
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setSource(resource);
							if (isCandidateComponent(sbd)) {
								if (debugEnabled) {
									logger.debug("Identified candidate component class: " + resource);
								}
								candidates.add(sbd);
							}
							else {
								if (debugEnabled) {
									logger.debug("Ignored because not a concrete top-level class: " + resource);
								}
							}
						}
						else {
							if (traceEnabled) {
								logger.trace("Ignored because not matching any filter: " + resource);
							}
						}
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to read candidate component class: " + resource, ex);
					}
				}
				else {
					if (traceEnabled) {
						logger.trace("Ignored because not readable: " + resource);
					}
				}
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}

2.1.2扫描的简单逻辑就是通过resourcePatternResolver解析指定路径下的所有类

2.1.3这是一个元数据阅读器MetadataReader可以获取类的ReSource,类元数据,还有注解元数据。门面设计模式

public interface MetadataReader {

	/**
	 * Return the resource reference for the class file.
	 */
	Resource getResource();

	/**
	 * Read basic class metadata for the underlying class.
	 */
	ClassMetadata getClassMetadata();

	/**
	 * Read full annotation metadata for the underlying class,
	 * including metadata for annotated methods.
	 */
	AnnotationMetadata getAnnotationMetadata();

}

2.1.4判断是否是符合条件的bean

/**
	 * Determine whether the given class does not match any exclude filter
	 * and does match at least one include filter.
	 * @param metadataReader the ASM ClassReader for the class
	 * @return whether the class qualifies as a candidate component
	 * 判断 是否不匹配任意一个exclude filter
	 * 且匹配至少一个include filter
	 * 在判断是否满足@Condition条件
	 */
	protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		for (TypeFilter tf : this.excludeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return false;
			}
		}
		for (TypeFilter tf : this.includeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return isConditionMatch(metadataReader);
			}
		}
		return false;
	}

到此完成了候选Bean的扫描和判断。 2.3 把2.1中符合条件的BeanDefinition 注册到BeaFactory工厂的BeanDefinitionMap变量中

public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		//	 注册beanDefinition
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		//如果bean指定了别名还会注册别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

registry.registerBeanDefinition() public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {

	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	/**
	 * 所有的BeanDefinition都会放在beanDefinitionMap变量中
	 * 01 先判断是否已经存在 同名的BeanDefinition
	 *  1.1 存在判断是否能覆盖
	 *  1.2直接覆盖同名的Bean,不同类型也能覆盖
	 * 02不存在同名的BeanDefinition
	 * 	2.1直接放入beanDefinitionMap,beanDefinitionNames变量中
	 * 	2.2清理缓存
	 */
	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		// 不允许覆盖,然后又重复扫描到了 -> 抛出异常
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
					"': There is already [" + existingDefinition + "] bound.");
		}
		else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
			/**
			 * 用框架定义的 Bean 覆盖用户自定义的 Bean
			 * 这里看注释是这么翻译的,但是在实际SpringBoot项目中:
			 * 如果没有手动disableAutoConfig 好像都是用户自定义的配置类覆盖了框架自动装配的。还得试验下。??
			 */
			if (logger.isWarnEnabled()) {
				logger.warn("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						existingDefinition + "] with [" + beanDefinition + "]");
			}
		}
		else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isInfoEnabled()) {
				logger.info("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	//02 不存在同名的BeanDefinition
	else {
		if (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				if (this.manualSingletonNames.contains(beanName)) {
					Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
					updatedSingletons.remove(beanName);
					this.manualSingletonNames = updatedSingletons;
				}
			}
		}
		else {
			// Still in startup registration phase
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	// 处理缓存
	if (existingDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}
	else if (isConfigurationFrozen()) {
		clearByTypeCache();
	}
}

到此,完成了所有包扫描的工作。并且把BeanDefinition注入到了BeanFactory。注意,到此任然没有初始化Bean,全部都是Bean的包装BeanDefinition。 这里放一张调试的截图,截止scan()执行完成,AnnotationConfigApplicationContext容器的初始化情况。

005 doscan小结.jpg

03刷新容器

refresh()刷新容器的内容较多,在下个章节阐述。