Spring - IOC源码分析(二)

分析register(componentClasses)方法

1、重点查看doRegisterBean()方法

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
			@Nullable BeanDefinitionCustomizer[] customizers) {

		/**
		 * AnnotatedGenericBeanDefinition可以理解为一种数据结构,是用来描述Bean的,这里的作用就是把传入的标记了注解
		 * 的类 ,转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
		 *
		 * -----------------------------------------------------------------------------------
		 * 通过AnnotatedGenericBeanDefinition的构造器获取配置类的beanDefinition,这里是不是
		 * 似曾相似,在注册ConfigurationClassPostProcessor类的时候,也是通过构造方法去获得BeanDefinition的,
		 * 只不过当时是通过RootBeanDefinition去获得,现在是通过AnnotatedGenericBeanDefinition去获得
		 * ------------------------------------------------------------------------------------
		 */
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
		/** 判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析 */
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(supplier);
		/** 解析bean的作用域,如果没有设置的话,默认为单例 */
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		// 获取beanName
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
		/** 解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description */
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		if (customizers != null) {
			for (BeanDefinitionCustomizer customizer : customizers) {
				customizer.customize(abd);
			}
		}

		/**
		 * 把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中(这个不是很重要,可以简单的理解为方便传参)
		 */
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

		/**
		 * 注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,
		 * DefaultListableBeanFactory维护着一系列信息,比如beanDefinitionNames,beanDefinitionMap
		 * beanDefinitionNames是一个List<String>,用来保存beanName
		 * beanDefinitionMap是一个Map,用来保存beanName和beanDefinition
		 */
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

2、进入registerBeanDefinition()方法,这个方法主要做了一件事,就是将definitionHolder封装对象里面的配置类的beanDefinition和beanName存放到beanDefinitionMap和beanDefinitionNames集合中

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

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

		// Register bean definition under primary name.
		/** 获取beanName */
		String beanName = definitionHolder.getBeanName();
		/** 注册我们配置类的beanDefinition和beanName到集合中 */
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

配置类的beanDefinition注册到beanDefinitionMap集合
在这里插入图片描述
配置类的beanName注册到beanNames集合
在这里插入图片描述
以常规方式去注册配置类,此方法中除了第一个参数,其他参数都是默认值。
1、通过AnnotatedGenericBeanDefinition的构造方法,获得配置类的BeanDefinition;
2、判断需不需要跳过注册,Spring中有一个@Condition注解,如果不满足条件,就会跳过这个类的
注册;
3、然后是解析作用域,如果没有设置的话,默认为单例;
4、获得BeanName;
5、 解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,
DependsOn,Role,Description;
6、把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中;
7、注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册;

以上注册配置类分析完毕。

refresh()方法

以上的分析只是实例化了一个工厂,在this()方法中注册了一些原生的内置的Bean(特别重要的ConfigurationClassPostProcessor);在register()方法中主要是注册了我们传入的配置类;真正的大头是在第三行代码:

refresh();

过于负责,这里简单说一下,就是解析配置类,找到配置类上的@ComponentScan注解找到需要扫描的包,扫描所有标注了@Controller、@Service、@Respository等注解,将符合条件的bean解析成beanDefinition并注册到集合中。

Spring Bean的生命周期

  1. 实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够被我们使用,因为连最基本的属性都没有设置,可以理解为
    连Autowired注解都是没有解析的;
  2. 填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了;
  3. 如果Bean实现了BeanNameAware接口,则调用setBeanName方法;
  4. 如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;
  5. 如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;
  6. 调用BeanPostProcessor的postProcessBeforeInitialization方法;
  7. 如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法;
  8. 如果Bean定义了init-method方法,则调用Bean的init-method方法;
  9. 调用BeanPostProcessor的postProcessAfterInitialization方法;当进行到这一步,Bean已经被准备就绪了,一直停留在应用的上下文中,直到被销毁;
  10. 如果应用的上下文被销毁了,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method声明了销毁方法也会被调用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值