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

共 10446字,需浏览 21分钟

 ·

2021-03-26 08:38

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

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 运行结果


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 检查:

————————————————

版权声明:本文为CSDN博主「你携秋月揽星河丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:

https://blog.csdn.net/qq_34125999/article/details/114858004




锋哥最新SpringCloud分布式电商秒杀课程发布

👇👇👇

👆长按上方微信二维码 2 秒





感谢点赞支持下哈 

浏览 39
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报