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

程序员考拉

共 10479字,需浏览 21分钟

 ·

2021-03-26 07:24

公众号关注 “GitHub今日热榜
设为 “星标”,带你挖掘更多开发神器!





引言


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





原文链接:https://blog.csdn.net/qq_34125999/article/details/114858004








关注GitHub今日热榜,专注挖掘好用的开发工具,致力于分享优质高效的工具、资源、插件等,助力开发者成长!







点个在看 你最好看


浏览 27
点赞
评论
收藏
分享

手机扫一扫分享

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

手机扫一扫分享

分享
举报