【一】Spring IoC 最全源码详解之 Spring容器创建流程

版权声明:本博客原创文章遵循CC BY-NC-SA 2.5 CN 协议 https://blog.csdn.net/wuyuwei/article/details/86697360

《圣经》旧约.创世纪:起初,神创造天地。地是空虚混沌,渊面黑暗; 神的灵运行在水面上。神说:“要有光。”就有了光。 神看光是好的,就把光暗分开了。 神称光为昼,称暗为夜。有晚上,有早晨,这是头一日。

                                                                                                                                《圣经》旧约.创世纪

目录

1.什么是BeanDefinition?

2.Spring是如何使用BeanDefinition的呢?

3. Spring容器的初始化过程

3.1.无参构造函数

3.1.1 创建AnnotatedBeanDefinitionReader

3.1.2 创建ClassPathBeanDefinitionScanner


1.什么是BeanDefinition?

Spring的Bean具有自己的属性、构造函数参数和很多具体的相关信息。BeanDefinition是用来描述Bean的这些信息的。类似与Java世界中,class Class这个类用来描述各种对象一样。

在java项目中,用户定义的各种xx.java文件要让JVM认识,需要事先通过编译器将其编译成xx.class文件。然后再通过ClassLoader读取xx.class文件将其加载到JMM的方法区Method Area。

在Spring项目中,用户定义了可以让Spring管理的注解类(@Component, @Service, @Repository)。Spring容器初始时,Spring就通过AnnotatedBeanDefinitionReader去获取这些类的注解信息,并将其翻译整合到beanDefinitionMap、beanDefinitionNames两个数据结构的实体中,等待后续的bean实例化过程使用。

BeanDefinition是什么模样呢?

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
	int ROLE_APPLICATION = 0;
	int ROLE_SUPPORT = 1;
	int ROLE_INFRASTRUCTURE = 2;
	void setParentName(@Nullable String parentName);
	String getParentName();
	void setBeanClassName(@Nullable String beanClassName);
	String getBeanClassName();
	void setScope(@Nullable String scope);
	String getScope();
	void setLazyInit(boolean lazyInit);
	boolean isLazyInit();
	void setDependsOn(@Nullable String... dependsOn);
	String[] getDependsOn();
	void setAutowireCandidate(boolean autowireCandidate);
	boolean isAutowireCandidate();
	void setPrimary(boolean primary);
	boolean isPrimary();
	void setFactoryBeanName(@Nullable String factoryBeanName);
	String getFactoryBeanName();
	void setFactoryMethodName(@Nullable String factoryMethodName);
	String getFactoryMethodName();
	ConstructorArgumentValues getConstructorArgumentValues();
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}
	MutablePropertyValues getPropertyValues();
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}
	void setInitMethodName(@Nullable String initMethodName);
	String getInitMethodName();
	void setDestroyMethodName(@Nullable String destroyMethodName);
	String getDestroyMethodName();
	void setRole(int role);
	int getRole();
	void setDescription(@Nullable String description);
	String getDescription();
	boolean isSingleton();
	boolean isPrototype();
	boolean isAbstract();
	String getResourceDescription();
	BeanDefinition getOriginatingBeanDefinition();
}

从定义中可以看出,BeanDefinition (bd)可以记录bean的相关定义,比如bean父类关系,作用域scope,是否懒加载islazy,依赖对象,是否可以被自动注入isAutowireCandidate,是否是FactoryBean等等常见属性。

2.Spring是如何使用BeanDefinition的呢?

我们以注解方式编写的项目举例来说,首先还是定义几个类:

package com.Hodey.learn.bean;

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

@Component("yadang")
public class Adam {

    private String name;

    @PostConstruct
    private void init(){
        name = "Adam";
    }

    public void sayHello(){
        System.out.println("你好,我是" + name + ".");
    }
}
package com.Hodey.learn.bean;

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;

@Component("xiawa")
public class Eve {

    private String name;

    @PostConstruct
    private void init(){
        name = "Eve";
    }

    public void sayHello(){
        System.out.println("你好,我是" + name + ".");
    }
}
package com.Hodey.learn.bean;

import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

@Component
@DependsOn("xiawa")
public class Human {

    public void sayHello(){
        System.out.println("大家好,欢迎来到伊甸园!");
    }
}
package com.Hodey.learn.service;

import com.Hodey.learn.bean.Adam;
import com.Hodey.learn.bean.Eve;
import com.Hodey.learn.bean.Human;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class GardenofEden {

    @Autowired
    private Adam adam;

    @Resource(name = "xiawa")
    private Eve eve;

    @Autowired
    private Human human;

    public void sayHello(){
        adam.sayHello();
        eve.sayHello();
        human.sayHello();
    }
}
package com.Hodey.learn;

import com.Hodey.learn.service.GardenofEden;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@EnableAutoConfiguration
@ComponentScan("com.Hodey")
public class CaseApplication {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext ctx =
				new AnnotationConfigApplicationContext(CaseApplication.class);
		GardenofEden garden = ctx.getBean(GardenofEden.class);
		garden.sayHello();
	}
}

工程结构目录如下:

要知道bd的来龙去脉,还得从Spring容器创建过程说起。

3. Spring容器的初始化过程

创建AnnotationConfigApplicationContext(CaseApplication.class),按照java的语法规则会先行调用其父类的构造方法,然后才调用自身的构造函数进行对象的创建。在DefaultResourceLoader中会初始化以下三个属性:

//类加载器Launcher$AppClassLoader
private ClassLoader classLoader;
//协议解析器容器
private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);
//配置文件缓存器
private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);

在AbstractApplicationContext类中主要初始化:

//确定日志类型,比如log4j,logback
protected final Log logger = LogFactory.getLog(getClass());
//创建beanFactory后置处理器
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
//创建事件监听器容器
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
/*resourceLoader:AnnotationConfigApplicationContext
* pathMatcher: AntPathMatcher ant风格的解析器 */
private ResourcePatternResolver resourcePatternResolver;

在GenericApplicationContext中创建Spring IoC最重要的对象beanFactory。

public GenericApplicationContext() {
	this.beanFactory = new DefaultListableBeanFactory();
}

最后才会调用AnnotationConfigApplicationContext(CaseApplication.class)的构造函数完成Spring容器的创建和初始化工作。

/* 输入若干个注解类,推导出其beanDefinition,之后自动刷新容器 */
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	this();//1.调用无参构造函数
	register(annotatedClasses);//2.将若干个配置类进行注册
	refresh();//3.refresh容器
}

3.1.无参构造函数

    进入其无参构造函数会发现容器的reader和scanner成员属性被创建出来。下面来看reader的创建过程。

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

3.1.1 创建AnnotatedBeanDefinitionReader

this.reader = new AnnotatedBeanDefinitionReader(this); this代表的是AnnotationConfigApplicationContext对象本身。回头再看看上面的类关系图谱,会发现AnnotationConfigApplicationContext对象本身就可以看作是BeanDefinitionRegistry,ResourceLoader和BeanFactory。依次进入其构造方法,最关键的一步是AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)。

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    //创建一个标准的环境对象StandardEnvironment
    //如果是web应用,这个环境对象将是StandardServletEnvironment
    //在SpringBoot项目中,该对象会被SpringBoot内核自动推断出来
    this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    this.registry = registry;
    //用于对含有@Condition注解的类进行特殊解析
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    //关键步骤
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

进入到该步骤的干货处:

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

	//从registry也就是AnnotationConfigApplicationContext中获取之前注册到它身上的bean工厂。
	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	/** 
	* 向Spring的beanFactory身上添加两个处理注解能力
	* 1. AnnotationAwareOrderComparator是处理@oder和@Priority
	* 2. ContextAnnotationAutowireCandidateResolver是处理@Lazy
	 */
	if (beanFactory != null) {		
		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
		}
		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		}
	}

	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

	/**
	* 以下是向bean工厂添加若干个Spring内部的配置类,这些配置类定义在org.springframework.context.annotation.AnnotationConfigUtils中
	* 1.defaultListableBeanFactory.beanDefinitionMap中添加配置类的<name ,bd>
	* 2.defaultListableBeanFactory.beanDefinitionNames中添加bd的name
	*/
	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
              //将返回的holder放入beanDefs这个Set中,其实并没有返回给外层
		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);
		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;
}

最终添加的bd是以下5个。

//配置类处理器
1.org.springframework.context.annotation.internalConfigurationAnnotationProcessor
//自动注入类处理器
2.org.springframework.context.annotation.internalAutowiredAnnotationProcessor
//通用注解类处理器
3.org.springframework.context.annotation.internalCommonAnnotationProcessor
4.org.springframework.context.event.internalEventListenerProcessor
5.org.springframework.context.event.internalEventListenerFactory

注册PostProcessor的代码是registerPostProcessor(registry, def, XXX)。

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

	//role有三个取值:ROLE_APPLICATION=0     代表是应用创建的bean
	//               ROLE_SUPPORT=1         代表某些起支持类作用的bean,比如在一些大型的configuration类中
	//               ROLE_INFRASTRUCTURE=2  Spring内部自己使用的bean,不对用户开放
	definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	//向defaultListableBeanFactory.beanDefinitionMap中添加配置类的<name ,bd>
	//向defaultListableBeanFactory.beanDefinitionNames中添加bd的name
	registry.registerBeanDefinition(beanName, definition);
	//返回一个holder,其实并没什么卵用
	return new BeanDefinitionHolder(definition, beanName);
}

当上述5个bd都完成注册后,reader 的创建和初始化过程就结束了。

3.1.2 创建ClassPathBeanDefinitionScanner

还是老规矩,先构造父类,再调用子类构造方法完成创建和初始化工作。父类的工作很简单,

ClassPathScanningCandidateComponentProvider
	//定义了扫描resource文件的路径
    private String resourcePattern = "**/*.class"
    private final List<TypeFilter> includeFilters = new LinkedList<>();
    private final List<TypeFilter> excludeFilters = new LinkedList<>();

子类ClassPathBeanDefinitionScanner的主要构建过程如下

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

	//dependencyCheck= DEPENDENCY_CHECK_NONE 默认不会进行依赖检查
	//autowireMode=AUTOWIRE_NO 默认的自动装配模式是NO,可以参考官网或者我的上一篇文章《关于Spring自动装配几个你所不知道的事》
	private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();

	//创建一个AnnotationBeanNameGenerator 可以参考官网或者我的上一篇文章《关于Spring自动装配几个你所不知道的事》
	private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
	//创建 @Scope注解类的解析器,并且默认不使用代理模式
	private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

	private boolean includeAnnotationConfig = true;

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

	this.registry = registry;

	if (useDefaultFilters) {
	//在scaner.includeFilters中添加javax.annotation.ManagedBean和javax.inject.Named两种注解类型filter
       //@javax.annotation.ManagedBean是JAVA EE6自身提供的注解类
	//@Inject、@Named、@Qualifier和@Provider是属于javax.inject.Named
	  registerDefaultFilters();
	}
	setEnvironment(environment);
	setResourceLoader(resourceLoader);
}

至此,AnnotationConfigApplicationContext.scaner就创建和初始化完毕了。随着scaner的初始化完毕,Spring容器的创建阶段就基本告一段落了。

如果将00:00-7:00的时刻表映射到Sping的启动流程的话,目前的时间大致应该是在00:30左右。夜生活才刚刚开始,后续文章敬请期待!

猜你喜欢

转载自blog.csdn.net/wuyuwei/article/details/86697360