Spring源码 BeanFactory的初探

看了Spring源码也有一阶段了,但是博客一直没有总结,因为源码这个东西,总结起来是真的难,想让别人看懂的博客更难。我也看了很多csdn上的一些别的Spring源码的博客,总觉得很多东西都讲的一知半解,大多数把一个方法复制过来,说下这个方法大致干啥就没了,很多重要的细节可能自己都没搞明白呢。我总结了他们写的源码博客的经验,打算来一个代码全程Debug的方式,很多重要的代码一行行解析的方式来记录。这样做的好处就是,别人看不到我的代码可以自己调试,不会无厘头吧。这个方式不好的地方就是,你需要把我的博客从第一篇看,不然很难跟上我的节奏。希望大家能对Spring的源码有所了解,我也能多spring的源码有更多的收获吧。

 

进入正题:

这篇的博客,本着先大后小的原则,我会大概过一遍spring的BeanFactory初始化过程,主要是为了了绘制下spring的BeanFactory到底放了哪些东西,还有Spring的一些定义之类的概念相关的东西,过一个眼熟。这个图绘制完成,再看Spring的源码,你就不会那么晕了,很多东西你都能从这个图上找到对应的名字。在开始之前,我先简单的介绍几个知识点,可能是你看源码出现最多的几个单词吧(个人的理解)
1BeanDefinition: 以后都简称bd,所谓的bean定义,可以类比理解,我们知道java可以用Class描述一个class,描述这个class有哪些feild method等信息,spring也这样做的,它用bd来描述bean的属性,描述一个bean是否懒加载,作用域,名称.....

2.beanFactory:bean工厂,就是存放bd的地方,当然还有很多东西,就是spring环境的原料和机器

废话不多说,我们来搭建这个最简单的项目吧。

 

1.导入依赖(只需要导入spring-content即可)

 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.9.RELEASE</version>
        </dependency>
    </dependencies>

2.创建一个配置类

@Configuration
@ComponentScan({"com.carry"})
public class Appconfig {
}

3.初始化spring的AnnotationConfigApplicationContext 

public class SpringDemoApplicationContext {
	
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.register(Appconfig.class);
	applicationContext.refresh();
	}
}

前期的准备工作就这么多,下面就要进入源码分析了,请做好,准备发车啦,准备好晕车药和红牛,干起来!!!

1.分析第一行代码:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

点进去看他的构造方法:

public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

我们有点java基础的都应该知道,实例化之类构造方法之前,会调用父类的构造方法,所以,我们要看

AnnotationConfigApplicationContext的父类GenericApplicationContext的构造方法:
public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

会创建一个我们这篇文章的主角,如果我们不点进去它的父类去看,你都不知道这个beanFactory在哪创建的

我们可以看下这个很神秘的bean工厂,里面有啥属性吧

	/** Map from serialized id to factory instance */
	private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
			new ConcurrentHashMap<>(8);

	/** Optional id for this factory, for serialization purposes */
	@Nullable
	private String serializationId;

	/** Whether to allow re-registration of a different definition with the same name */
	private boolean allowBeanDefinitionOverriding = true;

	/** Whether to allow eager class loading even for lazy-init beans */
	private boolean allowEagerClassLoading = true;

	/** Optional OrderComparator for dependency Lists and arrays */
	@Nullable
	private Comparator<Object> dependencyComparator;

	/** Resolver to use for checking if a bean definition is an autowire candidate */
	private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();

	/** Map from dependency type to corresponding autowired value */
	private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

	/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

	/** Map of singleton and non-singleton bean names, keyed by dependency type */
	private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

	/** Map of singleton-only bean names, keyed by dependency type */
	private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

	/** List of bean definition names, in registration order */
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

	/** List of names of manually registered singletons, in registration order */
	private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);

	/** Cached array of bean definition names in case of frozen configuration */
	@Nullable
	private volatile String[] frozenBeanDefinitionNames;

	/** Whether bean definition metadata may be cached for all beans */
	private volatile boolean configurationFrozen;

只把这边几个重要的属性,画在图上去

回到AnnotationConfigApplicationContext这个类的构造方法

this.reader = new AnnotatedBeanDefinitionReader(this);

创建了一个bean的读取器,顾名思义,给我一个类,这个reader可以转换成bd

我们可以看下,我们从这个reder的构造器点进去发生了什么?

	this.reader = new AnnotatedBeanDefinitionReader(this);


    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
	}

我们看下传一个this(AnnotationConfigApplicationContext对象)但是这边用BeanDefinitionRegistry去接收,说明了,这个BeanDefinitionRegistry和和AnnotationConfigApplicationContext是一样(因为AnnotationConfigApplicationContext的子类实现了BeanDefinitionRegistry这个接口哦)

看下构造方法:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		//委托
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

着重看下这个实现:AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		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);
		//BeanDefinitio的注册,这里很重要,需要理解注册每个bean的类型
		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 最终实现了 BeanPostProcessor
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			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);
			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);
			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,设置它的setDependencyComparator和提供延迟加载的ContextAnnotationAutowireCandidateResolver,具体代码这一次就不分析了,我们第一篇博客的目的是,清楚Spring的BeanFactory到底有什么东西的。

后面的代码就是构建这个方法的返回值:BeanDefinitionHolder,我们可以看下它的数据结构,就是封装下beaName和bd

我们详细看下这段代码:

	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		//BeanDefinitio的注册,这里很重要,需要理解注册每个bean的类型
		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(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME))

我们这个registry或者是spring这个大环境下是否存在一个这个名字的bd(我们这个可是一个很干净的registry,肯定没有,肯定能进这个if里面)

RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);

这段代码也很经典:从这段代码,我们可以知道一个东西,spring自己内部的内,装换成bd的方式:即,new一个RootBeanDefinition,并把类实例传过去即可

def.setSource(source);

这个代码没有用的,因为这个source是我们传过来的,默认传的就是null

beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

这个就是往bdh里面设置我们的bd,可以看下registerPostProcessor


	private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(beanName, definition);
		return new BeanDefinitionHolder(definition, beanName);
	}
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); 设置这个值为2,标识这个bd是人家spring自己的,和你没关系的
registry.registerBeanDefinition(beanName, definition);这行代码就是往我们的容器里面设置bd
return new BeanDefinitionHolder(definition, beanName); 返回bdh

这些代码执行完成之后,大家可以猜测下我们的registry里面有多少BeanDefinition了???

答案是:六个,具体的,可以自己debug看下,都是spring自己的bd

现在我们自己的bd图可以如下:

好了 this.reader = new AnnotatedBeanDefinitionReader(this);这行代码已经执行完成了,我们来看看我们从这行代码收获了什么:首先有了6个spring的bd,还知道了怎样从一个类转成bd的方式,也就是上图出现的元素,都是这行代码做的

下面来分析:this.scanner = new ClassPathBeanDefinitionScanner(this);

可以用来扫描包或者类,继而转换成bd,但是实际上,我们扫描包工作的scanner不是用的这个,是spring自己new的一个ClassPathBeanDefinitionScanner,这个我们后面后讲到的,大家不用着急,这里用其实也就是为了程序员你能在AnnotationConfigApplicationContext对象的scan方法

到此:

这里面的第一行代码执行完毕:我们应该有很大的收获吧,详情可以看图.

我们来分析applicationContext.register(Appconfig.class);第二行代码

我们可以一直点下去,里面都是方法的调用,真正干活的方法是doRegisterBean

/**
	 * Bean 定义读取器向容器注册注解 Bean 定义类
	 */
	<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
			@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

		// 根据指定的注解bean定义类,创建Spring容器中对注解Bean的封装的数据结构
		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(instanceSupplier);
		//解析注解 Bean 定义的作用域,若@Scope("prototype"),则 Bean 为原型类型;
   		//若@Scope("singleton"),则 Bean 为单利类型
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		// 为注解bean定义生成Bean名称
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		// 处理注解bean定义中的通用注解
		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		//如果在向容器注册注解 Bean 定义时,使用了额外的限定符注解,则解析限定符注解。
		//主要是配置的关于 autowiring 自动依赖注入装配的限定条件,即@Qualifier 注解
		//Spring 自动依赖注入装配默认是按类型装配,如果使用@Qualifier 则按名称
		if (qualifiers != null) {
			for (Class<? extends Annotation> qualifier : qualifiers) {
				//如果配置了@Primary 注解,设置该 Bean 为 autowiring 自动依赖注入装//配时的首选
				if (Primary.class == qualifier) {
					abd.setPrimary(true);
				}
				else if (Lazy.class == qualifier) {
					abd.setLazyInit(true);
				}
				//如果使用了除@Primary 和@Lazy 以外的其他注解,则为该 Bean 添加一
				//个 autowiring 自动依赖注入装配限定符,该 Bean 在进 autowiring
				//自动依赖注入装配时,根据名称装配限定符指定的 Bean
				else {
					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
				}
			}
		}
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}

		//创建一个指定Bean名称的bean定义对象,封装注解Bean定义数据
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		// 根据注解Bean定义类中配置的作用域,创建相应的代理对象
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		// 像ioc容器注册注解bean类定义对象
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

这里面的代码基本都有注释,我选几个重要的来讲一下(后面会全面的讲的,里面的很多方法,我都会一行一行带大家看的,还是那句话,看源码,先大后小,这篇博客的目的就是介绍spring的BeanFactory和一些常见的通用名称):

第一行代码就很重要,

// 根据指定的注解bean定义类,创建Spring容器中对注解Bean的封装的数据结构

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

我们上面从reader里面,知道,spring内部的对象转成bd是用RootBeanDefinition来new,

那么这行代码,告诉我们,加了注解的类可以通过new AnnotatedGenericBeanDefinition(annotatedClass);来创建

再看下最后一行的代码:

// 像ioc容器注册注解bean类定义对象

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

	/**
	 * 将解析的 BeanDefinitionHold 注册到容器
	 */
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		// 获取解析的BeanDefinition的名称
		String beanName = definitionHolder.getBeanName();
		//像ioc容器中注册BeanDefinition
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		// 如果BeanDefinition有别名。像容器注册其别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

这个就是用register注册我们的bd

这段代码执行完毕之后,我们BeanFactory里面就有7个bd了,六个spring自定义的(其中一个ConfigurationClassPostProcessor

很重要),还有一个就是我们的AppConfig,明白否?

我们打个refresh之前打个断点看下,执行完,前两行代码,我们的spring大环境都有神马东西,我们的BeanFactory有什么东西

再看看我们做的图都有哪些属性:

好了,至此,前两行代码执行的成果已经完成了。希望大家能坚持下去,我肯定会尽力写好这些spring的细节的(循环依赖,bean的生命周期,后置处理器等原理我都会分析的),希望大家能多多支持。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值