spring源码系列 bean定义过程

整理的灵感:被封号的怪咖凹凸曼
注解源码
bean定义和bean是有区别的

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);

AnnotationConfigApplicationContextextends GenericApplicationContext implements AnnotationConfigRegistry
会执行以下方法

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	//调用本身的两个方法 定义ban信息
	this();
	//注册bean配置类 MainConfig.class
	register(annotatedClasses);
	//刷新容器
	refresh();
}

步骤拆解

this();会调用本身的构造方法
在构造方法中做了两件事

this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);

this.reader = new AnnotatedBeanDefinitionReader(this);//获取环境之后创建几个bean 的定义
其中包含了以下七个bean的定义:

	/**
	 * The bean name of the internally managed Configuration annotation processor.
	 * 内部管理的Configuration注解处理器的Bean名称 rConfigurationClassPostProcessor
	 */
	public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";


	/**
	 * The bean name of the internally managed Autowired annotation processor.
	 * 内部管理的Autowired注解处理器的bean名称    AutowiredAnnotationBeanPostProcessor
	 */
	public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";


	/**
	 * The bean name of the internally managed Required annotation processor.
	 * 内部管理的Required注释处理器的bean名称。RequiredAnnotationBeanPostProcessor
	 */
	public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalRequiredAnnotationProcessor";


	/**
	 * The bean name of the internally managed JSR-250 annotation processor.
	 * 内部管理的 JSR-250注释处理器的bean名称。CommonAnnotationBeanPostProcessor
	 */
	public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalCommonAnnotationProcessor";


	/**
	 * The bean name of the internally managed JPA annotation processor.
	 *  内部管理的JPA 注释处理器的bean名称。
	 * 读取以下这个
	 * 	private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME =
			"org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";

	 *   def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
	 */
	public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME =
			"org.springframework.context.annotation.internalPersistenceAnnotationProcessor";


	/**
	 * The bean name of the internally managed @EventListener annotation processor.
	 * 内部管理的@EventListener 注释处理器的bean名称。EventListenerMethodProcessor
	 */
	public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =
			"org.springframework.context.event.internalEventListenerProcessor";


     /**
	 * The bean name of the internally managed EventListenerFactory.
	 * 内部管理的EventListenerFactory的bean名称。DefaultEventListenerFactory
	 */
	public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =
			"org.springframework.context.event.internalEventListenerFactory";

this.scanner = new ClassPathBeanDefinitionScanner(this);中比较重要的就是注册了几个bean的过滤器
Component
javax.annotation.ManagedBean
javax.inject.Named
说白了就是注册具有@Component元注释的所有注释,包括@ Repository,@ Service和@Controller构造型注释

另外做几个补充:

实现 ApplicationListener 监听接口,可以在refresh刷新容器过程中(初始化应用程序事件多播器和初始化监听器之后)利用观察者模式监听到发出来的信息。
实现BeanFactoryPostProcessor 接口  beanFactory后置处理器	 可以在beanFactory创建完成之后,bean实例话之前对bean的初始化信息做修改
实现BeanDefinitionRegistryPostProcessor 接口 Bean定义注册表后处理器   可以在bean定义没有加载之前,自己做加入。

refresh()刷新容器原理:
在这里插入图片描述

		   // Prepare this context for refreshing.
			//上下文刷新准备
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//告诉子类刷新内部bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//在标准初始化之后,修改应用程序上下文的内部bean工厂。所有bean定义都将被加载,但是还没有实例化bean *。这允许在某些ApplicationContext实现中注册特殊* BeanPostProcessors等
				//目前方法没有明确实现
				postProcessBeanFactory(beanFactory);
在这里调用invokeBeanFactoryPostProcessors方法,进行装载bean定义信息。
调用PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());方法,意思是在bean工厂的后置处理器,开始加载bean定义。

从下面可以看出这里从工厂中取出了在之前放到里面的一个org.springframework.context.annotation.internalConfigurationAnnotationProcessor
结合上面的代码定义得出这是个解析Configuration的定义。先进行排序,之后放入registryProcessors中

在这里插入图片描述

简单复述一下这里的逻辑,首先去获取实现了PriorityOrdered接口的  返回的值越小优先级越高
根据接口返回值做一个排序
在获取实现了Ordered接口的
根据返回值做排序
最后获取普通的

这里是处理BeanDefinitionRegistryPostProcessors  实现了这个接口的都会在这里被处理
因为一开是进入的时候有几个注解 org.springframework.context.annotation.internalConfigurationAnnotationProcessor
这个实现了BeanDefinitionRegistryPostProcessors接口 且优先级最高  所以会调用实现方法  就开始加载config注解下的定义信息

接着开始加载BeanFactoryPostProcessors ,跟上面的逻辑是一样的
BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口  所以实现BeanDefinitionRegistryPostProcessor的类			这里也会被处理


可以看出这里循环调用postProcessor.postProcessBeanDefinitionRegistry(registry);方法
从注册表中的配置类派生更多的Bean定义

在这里插入图片描述

接着哈希出一个int值,判断注册后处理的集合是否存在。判断工厂后置处理中是否存在,不存在则加入。
最后调用 processConfigBeanDefinitions(registry); 方法,开始正式基于@Configuration处理bean定义

在这里插入图片描述

这里我们发现开始解析已经存在的一些bean定义,我们之前在refresh()方法加载之前,加载了七个bean定义和一个配置类
这里取出之后判断是否是配置类,并检查是否为配置类。会发现只有一个mainconfig 是(我们加了config注解),并new  Bean定义持有人 (BeanDefinitionHolder)放入集合中

在这里插入图片描述

下面代码就是生成bean名称(没太仔细看,不太关注)有时间在看
接着看到根据环境 配置解读器和名称生成器等对象创建了一个parser对象(解析config对象)
接着调用了parse方法  非常非常重要的一步!!!

在这里插入图片描述
在这里插入图片描述

这里就不截屏了 先是循环获取到bean定义信息,然后判断是否是注解形式。接着重载parse方法
调用processConfigurationClass方法  传入ConfigurationClass对象(根据注解原信息和beanname构建)注解原信息我们指放在maincofig上的注解  

 直接上代码
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}
		
		//进入方方法从本身的的集合中尝试获取配置类,这里获取判null,我们第一次进入 肯定是没有的

		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
		if (existingClass != null) {
			if (configClass.isImported()) {
				if (existingClass.isImported()) {
					existingClass.mergeImportedBy(configClass);
				}
				// Otherwise ignore new imported config class; existing non-imported class overrides it.
				return;
			}
			else {
				// Explicit bean definition found, probably replacing an import.
				// Let's remove the old one and go with the new one.
				this.configurationClasses.remove(configClass);
				for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
					if (configClass.equals(it.next())) {
						it.remove();
					}
				}
			}
		}

		
		//开始递归处理配置类及其超类层次结构
		//得到SourceClass
		SourceClass sourceClass = asSourceClass(configClass);
		do {
			//核心方法
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}
开始进入doProcessConfigurationClass方法,spring有个特别好玩的地方,就是做事的方法都有个do
可以看出下面很重要了
总结:处理几个注解,bean ComponentScan  bean注解只加入到集合  不定义  ComponentScan直接扫描到定义
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {

		// Recursively process any member (nested) classes first
		processMemberClasses(configClass, sourceClass);

		// 处理 @PropertySource 注解  我们没用过,也没加直接忽略
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			else {
				logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}

		// 处理 @ComponentScan 注解,这个有,获取到注解信息。比如我们配置的value值
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
				//开始循环获取到的所有的注解
			for (AnnotationAttributes componentScan : componentScans) {
				// 这里获取到所有的扫描到的子bean定义
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				// 这里获取到所有的子定义循环
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					//检查配置 类是否继续含有Component ComponentScan Import ImportResource注解 有的话再滚去解析一遍
						//知道将所有的底解析完 不在含有这几个注解  @controller@ service 这些都得在这个地方再进去解析
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						//开始接着解析
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// 这个方法用栈处理 @Import 注解  判断是否是ImportSelector  这个好像是boot自动装配的核心  ImportBeanDefinitionRegistrar 我们这里都不是
		 //那就把他当作@Configuration处理  指定的bean没有被定义 除非你指定的bean还有controller server import等注解
		processImports(configClass, sourceClass, getImports(sourceClass), true);

		// Process any @ImportResource annotations  用的不多
		if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
			AnnotationAttributes importResource =
					AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
			String[] resources = importResource.getStringArray("locations");
			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

		// Process individual @Bean methods  bean注解 扫面出来方法 放入集合
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
		processInterfaces(configClass, sourceClass);

		// Process superclass, if any 不知道干啥 
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// No superclass -> processing is complete
		return null;
	}

componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());方法调用之后就是一顿赋值 不细看了 最后调用一个doscan方法出入了包名 得知是componentScan注解的value的值

	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
		for (String basePackage : basePackages) {
			//这个方法也很好玩 查找候选组件  拼接路径 查看文件是否可读   扫到含有component的注解的类定义成bean定义 
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				//解析元数据
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				//设置单例
				candidate.setScope(scopeMetadata.getScopeName());
				//生成bean名称
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				//检查是否已存在bean名称等
				if (checkCandidate(beanName, candidate)) {
					//就是注册bean定义
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

整体出来后进入这个方法
去上面找找 整理整理逻辑 不行就自己再debug

在这里插入图片描述

this.reader.loadBeanDefinitions(configClasses);开始进入这个方法
可以看出下图 我们的bean模型都出来 但是通过import指定的service类没有beanName 而且缺少了一个用@bean注解定义的dao类接着看

在这里插入图片描述

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;
	}
		//判断是否是import导入的  没有名字的service类在这里正式定义到工厂中 定义不是注册
	if (configClass.isImported()) {
		registerBeanDefinitionForImportedConfigurationClass(configClass);
	}
	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		//这里加载通过bean注解的
		//设置名称 默认以方法名称起名
		//设置init和销毁方法 有默认的
		//设置注入方式 代理等东西注册定义到bean工厂
		loadBeanDefinitionsForBeanMethod(beanMethod);
	}

	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

到现在位置@config注解注册bean定义过程结束,只是定义 还没有注册

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值