Spring Bean 的实例化过程源码解析

引言

概述: Spring Bean 创建源码分析系列

【1】Spring Bean 的实例化过程源码解析
【2】Spring 依赖注入(DI) 源码解析
【3】Spring 三级缓存解决循环依赖

1 工程概述

Spring Bean 的实例化过程源码解析_第1张图片

1.1 pom

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring.version>5.2.8.RELEASE</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
        <!-- 日志相关依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.10</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.2</version>
        </dependency>
    </dependencies>

1.2 bean

@Data
@Component
public class CqCityBean {

    private static final String NAME = "重庆";

    public String getCityName(){

        return NAME;
    }

}

@Data
public class StudentBean {

    public final String name = "rosh";

    public final Integer age = 18;

    public StudentBean(){

        System.out.println("invoke StudentBean NoArgsConstructor");

    }

}
 
 
@Data
@Component
public class XaCityBean {

    private static final String NAME = "西安";

    public String getCityName(){

        return NAME;
    }

}


1.3 service

@Service
public class CityService {

    @Autowired
    public CityService(CqCityBean cq, XaCityBean xa) {
        System.out.println(cq.getCityName());
        System.out.println(xa.getCityName());
    }

}

1.4 applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
	http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd"
       default-lazy-init="false">

    <context:component-scan base-package="com.rosh.service,com.rosh.bean"/>

    <bean id="student" class="com.rosh.bean.StudentBean"/>

</beans>

1.5 RoshTest

public class RoshTest {

    @Test
    public void mainTest(){
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        applicationContext.close();

    }

}

1.6 运行结果

Spring Bean 的实例化过程源码解析_第2张图片

2 主流程源码Debug

Spring Bean 的实例化过程源码解析_第3张图片
Spring Bean 的实例化过程源码解析_第4张图片
Spring Bean 的实例化过程源码解析_第5张图片
Spring Bean 的实例化过程源码解析_第6张图片
Spring Bean 的实例化过程源码解析_第7张图片
Spring Bean 的实例化过程源码解析_第8张图片
Spring Bean 的实例化过程源码解析_第9张图片

主流程时序图:
Spring Bean 的实例化过程源码解析_第10张图片

3 createBeanInstance 源码解析

描述: 该方法主要作用bean的构造方法创建对象

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		//如果有FactoryMethodName属性
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?

		/**
		 * 【1】实例化Bean带有@Autowired注解的构造函数
		 *
		 * (1) 找到带有@Autowired注解的有参构造函数
		 * (2) 使用构造函数创建对象
		 */
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// 调用无参构造方法创建bean
		return instantiateBean(beanName, mbd);
	}

3.1 创建无参bean对象

Spring Bean 的实例化过程源码解析_第11张图片
Spring Bean 的实例化过程源码解析_第12张图片
Spring Bean 的实例化过程源码解析_第13张图片
Spring Bean 的实例化过程源码解析_第14张图片
Spring Bean 的实例化过程源码解析_第15张图片
描述: 使用反射调用无参构造函数创建对象
Spring Bean 的实例化过程源码解析_第16张图片
Spring Bean 的实例化过程源码解析_第17张图片

3.2 @Autowired构造创建有参对象

Spring Bean 的实例化过程源码解析_第18张图片
Spring Bean 的实例化过程源码解析_第19张图片

3.2.1 AutowiredAnnotationBeanPostProcessor

determineCandidateConstructors 方法分析,获取@Autowired 有参构造函数
Spring Bean 的实例化过程源码解析_第20张图片
Spring Bean 的实例化过程源码解析_第21张图片
Spring Bean 的实例化过程源码解析_第22张图片
Spring Bean 的实例化过程源码解析_第23张图片
Spring Bean 的实例化过程源码解析_第24张图片
Spring Bean 的实例化过程源码解析_第25张图片

3.2.2 ConstructorResolver

ConstructorResolver类autowireConstructor方法创建对象
Spring Bean 的实例化过程源码解析_第26张图片
Spring Bean 的实例化过程源码解析_第27张图片
Spring Bean 的实例化过程源码解析_第28张图片
Spring Bean 的实例化过程源码解析_第29张图片
描述: 创建参数
Spring Bean 的实例化过程源码解析_第30张图片
Spring Bean 的实例化过程源码解析_第31张图片
Spring Bean 的实例化过程源码解析_第32张图片
Spring Bean 的实例化过程源码解析_第33张图片
Spring Bean 的实例化过程源码解析_第34张图片
Spring Bean 的实例化过程源码解析_第35张图片
在这里插入图片描述
Spring Bean 的实例化过程源码解析_第36张图片
Spring Bean 的实例化过程源码解析_第37张图片
Spring Bean 的实例化过程源码解析_第38张图片

3.3 无@Autowired 构造创建有参对象

Spring Bean 的实例化过程源码解析_第39张图片
Spring Bean 的实例化过程源码解析_第40张图片

3.3.1 Debug

Spring Bean 的实例化过程源码解析_第41张图片

AutowiredAnnotationBeanPostProcessor 检查:
Spring Bean 的实例化过程源码解析_第42张图片
Spring Bean 的实例化过程源码解析_第43张图片

你可能感兴趣的:(Spring,源码解析与实战)