面试官听了也赞不绝口的Spring源码剖析实例化过程

Java
226
0
0
2023-06-01
标签   Spring

前言

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="#34;
       xmlns:xsi="#34;
       xmlns:context="#34;
       xsi:schemaLocation="


    
    #34;
       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();
    }
}  

读者福利:转发+关注 私信【学习笔记】获取小编整理好的Java知识点学习笔记一份。

1.6 运行结果

2 主流程源码Debug

主流程时序图:

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对象

描述: 使用反射调用无参构造函数创建对象

3.2 @Autowired构造创建有参对象

3.2.1 AutowiredAnnotationBeanPostProcessor

determineCandidateConstructors 方法分析,获取@Autowired 有参构造函数

3.2.2 ConstructorResolver

ConstructorResolver类autowireConstructor方法创建对象

描述: 创建参数

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

3.3.1 Debug

AutowiredAnnotationBeanPostProcessor 检查:

读者福利:转发+关注 私信【学习笔记】获取小编整理好的Java知识点学习笔记一份。