Spring【版本5.2.2】容器初始化过程(一)this与register

因为我还是比较喜欢转载的,人家总结的漂漂亮亮的,何苦自己在整轮子,但是关于spring容器初始化过程相关文章,是在找不到一个合适的,所以自己整理了一篇。
废话不多说,直接上代码,因为后面废话更多,如有错误,留言指正,都是学习
首先准备一个测试代码:

public class IocTest2 {
	public static void main(String[] args) {
		BeanFactory context = new AnnotationConfigApplicationContext(IcoAppConfig2.class);
		Bean1 bean = context.getBean(Bean1.class);
		bean.say();
	}
}
public class Bean1 {
	public void say(){
		System.out.println("say");
	}
}
@Configuration
public class IcoAppConfig2 {
	@Bean
	public Bean1 bean1(){
		return new Bean1();
	}
}

下面开始根据断点,一步一步记录一下,咱们Spring容器做了啥

1. AnnotationConfigApplicationContext

先看一下AnnotationConfigApplicationContext的继承关系
AnnotationConfigApplicationContext的继承关系

	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		// 由于他有父类,故而先调用父类的构造方法。然后调用自己的构造方法
		this();
		register(componentClasses);
		refresh();
	}

1. 先调用当前类的构造方法

因为当前类的父类有构造方法,所以先调用父类的构造方法

  1. 先在DefaultResourceLoader中初始化一个ClassLoader
  2. 在AbstractApplicationContext 初始化一个ResourcePatternResolver
  3. 在GenericApplicationContext中初始化一个DefaultListableBeanFactory✨
  4. 进入AnnotationConfigApplicationContext的构造函数中
	/**
	 * 初始化一个bean的读取和扫描器,容器不包含任何 Bean 信息,如果直接调用构造方法,需要调用器register()去注册配置类,
	 * 并调用refresh() 方法刷新容器,触发容器对注解bean的载入、解析和注册过程
	 * Create a new AnnotationConfigApplicationContext that needs to be populated
	 * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigApplicationContext() {
		/*
		 * 父类的构造方法
		 * 创建一个读取被注解的Bean定义读取器
		 * 什么是bean定义?BeanDefinition
		 */
		this.reader = new AnnotatedBeanDefinitionReader(this);

		/*
		 * 可以用来扫描包或者类,继而转换成BeanDefinition,但是实际上我们扫描包工作不是scanner这个对象来完成的,
		 * 而是spring自己new的一个ClassPathBeanDefinitionScanner,
		 * 具体是在ComponentScanAnnotationParser.parse这个方法中new的scanner
		 * 这里的scanner仅仅是为了程序员能在外部调用AnnotationConfigApplicationContext对象的scan方法。
		 * */
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

先说说初始化的reader做了哪些事情:

	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}
  • conditionEvaluator 是一个内部类,用于evaluate Conditional 注解的,这里面会初始化ConditionContextImpl对象
  • AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);这个方法,做了很多事情,我们看一下源码
	/**
	 * 该方法主要是向容器注册了一组基础设施PostProcessor bean定义,
	 * 这些bean定义生成的PostProcessor实例被框架自己用于识别注解配置类中的bean定义。
	 * 它们里面还有一些作用于BeanDefinitionRegistry(容器级)的BeanDefinitionRegistryPostProcessor,
	 * 和作用于BeanFactory(容器级)的BeanFactoryPostProcessor,其它才是一般bean级别的BeanPostProcessor。
	 * Register all relevant annotation post processors in the given registry.
	 * @param registry the registry to operate on
	 * @param source the configuration source element (already extracted)
	 * that this registration was triggered from. May be {@code null}.
	 * @return a Set of BeanDefinitionHolders, containing all bean definitions
	 * that have actually been registered by this call
	 */
	public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		// registry是GenericApplicationContext类型的,就返回他的DefaultListableBeanFactory对象
		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				// AnnotationAwareOrderComparator主要能解析@Order注解和@Priority
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				// ContextAnnotationAutowireCandidateResolver提供处理延迟加载功能
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		// BeanDefinition的注册,这里很重要,需要理解注册每个bean的类型 知识点:beanPostProcessor和beanFactoryPostProcessor
		// why?因为需要在invokeBeanFactoryPostProcessors
		// invokeBeanFactoryPostProcessors主要是在spring的beanFactory初始化的过程中去做一些事情,怎么来做这些事情呢?
		// 委托了多个实现了BeanDefinitionRegistryPostProcessor或者BeanFactoryProcessor接口的类来做这些事情,有自定义的也有spring内部的
		// 其中ConfigurationClassPostProcessor就是一个spring内部的BeanDefinitionRegistryPostProcessor。
		// 因为如果你不添加这里就没有办法委托ConfigurationClassPostProcessor做一些功能
		// 到底哪些功能?参考下面的注释
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			// 需要注意的是:ConfigurationClassPostProcessor的类型是BeanDefinitionRegistryPostProcessor,
			// 而 BeanDefinitionRegistryPostProcessor 最终实现BeanFactoryPostProcessor✨这个接口
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			// AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor
			// MergedBeanDefinitionPostProcessor最终实现BeanFactoryPostProcessor这个接口
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_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);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

		return beanDefs;
	}

上面的代码,会在beanFactory.beanDefinitionNames这个map中添加五个PostProcessor,这个很重要

beanDefinitionNames
0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
3 = "org.springframework.context.event.internalEventListenerProcessor"
4 = "org.springframework.context.event.internalEventListenerFactory"

再说说初始化的scanner做了哪些事情:

	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {
		// 为容器设置加载Bean定义的注册器
		this.registry = registry;

		if (useDefaultFilters) {
			/* 注册@Component的默认过滤器。这将隐式注册所有具有@Component元注释的注解,
			 * 包括@Repositor、@Service@Controller构造型注解。
			 * 同时还支持javax.annotation.ManagedBean,javax.inject.Named这两个注解
			 */
			registerDefaultFilters();
		}
		setEnvironment(environment);
		// 为容器设置资源加载器
		setResourceLoader(resourceLoader);
	}

所以说, 他并没有实质上做什么事情, 也没有去scan,也没有去实例化

2. register(componentClasses)

这个componentClass,也就是我们从测试方法中传过来的IcoAppConfig2这个类。跟踪源码,我们找到主要的方法,其中只有第一个参数Class beanClass是有值的,其他都是null

	/**
	 * Bean定义读取器向容器注册注解Bean定义类
	 * 下面的这句话就是说:根据Bean的注解获取元数据
	 * Register a bean from the given bean class, deriving its metadata from
	 * class-declared annotations.
	 * @param beanClass the class of the bean 根据类型byBeanType
	 * @param name an explicit name for the bean 根据名称 byBeanName 当前null
	 * @param supplier a callback for creating an instance of the bean 创建bean的实例的回调 当前null
	 * (may be {@code null})
	 * @param qualifiers specific qualifier annotations to consider, if any,  主要是@Qualifier注解 当前null
	 * in addition to qualifiers at the bean class level
	 * @param customizers one or more callbacks for customizing the factory's 当前null
	 * {@link BeanDefinition}, e.g. setting a lazy-init or primary flag
	 * @since 5.0
	 */
	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {
		// 根据指定的注解Bean定义类,创建Spring容器中对注解Bean的封装的数据结构 就是这个BeanClass的表述
		// AnnotatedGenericBeanDefinition 包含了类的其他信息,比如一些元数据,scope,lazy等等
		// 跟踪源码发现,他实际上是初始化了beanClass,metadata
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);

		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(supplier);
		// 解析注解Bean的作用于,
		// 若@Scope("prototype"),则Bean为原型类型;
		// 若@Scope("singleton"),则Bean为单态类型;
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		// 为注解Bean定义设置作用域,这里是singleton
		abd.setScope(scopeMetadata.getScopeName());
		// 为注解Bean定义生成Bean名称,这里是icoAppConfig2
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		// 处理注解Bean定义中的通用注解,主要是@Primary、@Lazy,@DependsOn、@Primary、@Role
		// 处理完成之后processCommonDefinitionAnnotations中依然是把他添加到数据结构[adb]中 
		// @See 参加后面的processCommonDefinitionAnnotations说明
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

		// 如果在向容器注册注解Bean定义时,使用了额外的限定符注解,则解析限定符注解。
		// 主要是配置的关于autowiring自动依赖注入装配的限定条件,即@Qualifier注解
		// Spring自动依赖注入装配默认是按类型装配,如果使用@Qualifier则按名称
		if (qualifiers != null) { // 咱们这里面是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);
				}
				else {
					// 如果使用了除@Primary和@Lazy以外的其他注解,则为该Bean添加一
					// 个autowiring自动依赖注入装配限定符,该Bean在进autowiring
					// 自动依赖注入装配时,根据名称装配限定符指定的Bean
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}
		// 创建一个指定Bean名称的Bean定义对象,封装注解Bean定义类数据
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		// 根据注解Bean定义类中配置的作用域,创建相应的代理对象
		// ScopedProxyMode需要结合Web去理解
		// 见#applyScopedProxyMode说明
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		// 把上述的数据结构abd,注册给registry
		// registry就是AnnotationConfigApplicationContext
		// AnnotationConfigApplicationContext在初始化的时候通过调用父类的构造方法,
		// 实例化了一个DefaultListableBeanFactory
		// registerBeanDefinition里面就是把definitionHolder这个数据结构包含的信息注册到
		// @See DefaultListableBeanFactory工厂,参考registerBeanDefinition 说明
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

processCommonDefinitionAnnotations说明

	/**
	 * 作用:处理Bean定义中通用注解
	 * 输入参数一般是某个基于注解的bean定义(类级别或者方法级别bean定义),
	 * 以AnnotatedBeanDefinition类型存在的一个对象实例,
	 * 可能创建者已经设置了该对象的一些成员属性,但是更多的成员属性还存在于原始bean定义的元数据中,
	 * 该方法从原始bean定义的元数据中获取那些通用的注解信息:@Lazy,@DependsOn,@Role,@Description,
	 * 然后设置AnnotatedBeanDefinition实例相应的属性。
	 *  参数 abd : Bean定义
	 *  参数 metadata : 类型上的注解元数据信息
	 */
	static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
		AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
		// 如果Bean定义中有@Lazy注解,则将该Bean预实例化属性设置为@lazy注解的值
		if (lazy != null) {
			abd.setLazyInit(lazy.getBoolean("value"));
		}
		else if (abd.getMetadata() != metadata) {
			lazy = attributesFor(abd.getMetadata(), Lazy.class);
			if (lazy != null) {
				abd.setLazyInit(lazy.getBoolean("value"));
			}
		}
		// 如果Bean定义中有@Primary注解,则为该Bean设置为autowiring自动依赖注入装配的首选对象
		if (metadata.isAnnotated(Primary.class.getName())) {
			abd.setPrimary(true);
		}
		AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
		if (dependsOn != null) {
			abd.setDependsOn(dependsOn.getStringArray("value"));
		}
		// 如果Bean定义中有@DependsOn注解,则为该Bean设置所依赖的Bean名称,
		// 容器将确保在实例化该Bean之前首先实例化所依赖的Bean✨
		AnnotationAttributes role = attributesFor(metadata, Role.class);
		if (role != null) {
			abd.setRole(role.getNumber("value").intValue());
		}
		AnnotationAttributes description = attributesFor(metadata, Description.class);
		if (description != null) {
			abd.setDescription(description.getString("value"));
		}
	}

applyScopedProxyMode说明

	/** 根据作用域为Bean应用引用的代理模式 */
	static BeanDefinitionHolder applyScopedProxyMode(
			ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
		// 获取注解Bean定义类中@Scope注解的proxyMode属性值
		ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
		// 如果配置的@Scope注解的proxyMode属性值为NO,则不应用代理模式
		if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
			return definition;
		}
		// 获取配置的@Scope注解的proxyMode属性值,如果为TARGET_CLASS
		// 则返回true,如果为INTERFACES,则返回false
		boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
		// 为注册的Bean创建相应模式的代理对象
		return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
	}

registerBeanDefinition说明

根据断点,我们发现他调用的是GenericApplicationContext.registerBeanDefinition这个方法,然后这个方法,最终还是走到了DefaultListableBeanFactory里面,先看看beanDefinitionMap中有没有,然后判断一下hasBeanCreationStarted()🤔这个方法,发现都不符合,于是乎就是下面最终的代码,是的,上面噼里啪啦,就是为了下面三行

		// Still in startup registration phase
		this.beanDefinitionMap.put(beanName, beanDefinition);
		this.beanDefinitionNames.add(beanName);
		removeManualSingletonName(beanName);

末尾添加一句,感谢子路老师的讲解,懂得人自然懂。
未完待续。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值