关于后端:0源码基础学习Spring源码系列一Bean注入流程

4次阅读

共计 25435 个字符,预计需要花费 64 分钟才能阅读完成。

作者:京东科技 韩国凯

通过本文,读者能够 0 源码根底的初步学习 spring 源码,并可能触类旁通从此进入源码世界的大米!
因为是第一次浏览源码,文章之中不免存在一些问题,还望包涵斧正!
文章 demo 源码:http://xingyun.jd.com/codingR…

一、@Autowired 与 @Resource 的区别

用一句话总结两者的区别就是:@Autowired 会先通过类型注入,即 byType,当存在有 多个类型 时会通过名称注入。@Resource 则相同,会先通过名称注入,即 byName,当名称不存在或有多个名称时 会通过类型注入。

那么通过名称注入与通过类型注入有什么区别呢?

// 创立接口
interface StuService{String getName();
}

@Service
//Stu2 实现接口并注册 bean
class Stu2 implements StuService{
    @Override
    public String getName() {return "stu2";}
}

@Service
//Stu3 实现接口并注册 bean
class Stu3 implements StuService{
    @Override
    public String getName() {return "stu3";}
}

1.1 @Autowired

那么此时如果咱们对 StuService注入,@Autowired 能够抉择注入的类型就有两个,别离是 Stu2与 Stu3

须要留神的是,类型有很多种抉择:

  1. 当注册 bean 与获取 bean 为同一个类时,类型只有这个类自身。

例如,咱们有获取 session 的工具类,须要将其注入到 spring 之中,

@Component
class SessionUtil{public String getSession(){return "session";}
}

只有一个类,间接注册 bean,应用时能够任意抉择

@Autowired
SessionUtil sessionUtil;

此时 @Autowired 只有一个注册类型,间接注入。

  1. 当注册 bean 有多个时,类型为所有注册的 bean,实现形式有:实现接口、继承、通过其余形式,例如 xml 配置注册 bean。

例如上述 StuService有多个实现类,每个实现类都注册了 bean,因而 @Autowired 能够抉择的类型就有两个。

@Autowired
StuService stu;

根据上述的 @Autowired 逻辑,此时有多个类型,那么会依据 bean name 查找,(即类名首字母小写的),发现 stu没有对应的实现类,

此时会报错:

Field stu in com.example.demo.spring.Stu1 required a single bean, but 2 were found:

只须要将 stu 替换成 stu2或 stu3即可实现注入。

继承和其余形式同时有多个 bean 注入时同理。

因而,@Autowired 中类型的定义能够归结为:当注册 bean 有多个时,类型为所有注册的 bean,实现形式有:实现接口、继承、通过其余形式,例如 xml 配置注册 bean 或者 @Bean 注册。

1.2 @Resource

  1. 当只有一个 bean 时,能够间接注册
@Autowired
SessionUtil sessionUtil;
  1. 当有多个 bean 注册时,如果未指定名称,则 bean name 为类名首字母小写,指定了 bean 名称则注册名称为该名称。

例如上文中 Stu1 Stu2都未指定 bean 名称,因而两者的 bean 名称别离为 stu1 stu2

当应用 @Bean 在办法上注册 bean,此时名称为办法名称。

@Bean()
public Student getStudent(){Student student = new Student();
    student.setName("bob");
    student.setId(26);
    return student;
}

此时该 bean 名称为 getStudent

同样,咱们也能够注册 bean 时自定义 bean 名称

@Bean("stu1")
public Student getStudent(){Student student = new Student();
    student.setName("bob");
    student.setId(26);
    return student;
}

@Service("stu2")
class Stu2 implements StuService{
    @Override
    public String getName() {return "stu2";}
}

@Component("stu3")
class Stu3 implements StuService{
    @Override
    public String getName() {return "stu3";}
}

在援用时指定 bean:

@Resource(name = "stu2")
private StuService stu1;

1.3 @Autowired

当咱们应用 @Resource 时,会依据名称也就是 stu2去查问,此时 bean 名称只有一个,查到返回

@Resource
private Stu3 stu2;

然而在执行时却发现报错:

Bean named 'stu2' is expected to be of type 'com.example.demo.spring.Stu3' but was actually of type 'com.example.demo.spring.Stu2'

这是因为只依据了 bean 名称去查问,却没有依据 bean 类型,查到的是 Stu2 类型的 bean,然而冀望的却是Stu3,因而会产生类型不匹配。

二、SpringIOC 的 Bean 注入流程

spring 的注册流程次要蕴含两个局部:

  1. 容器的启动阶段及预热工作
  2. Bean 的注入流程

先理解一下几个概念:

2.1 概念介绍

2.1.1 配置元数据

存在于磁盘上的我的项目中用于形容一个 bean 的数据,能够是 xml、properties、yaml 等动态文件,也能够是各种注解形容的对应信息,例如 @Service、@Component 形容的一个 bean 的信息。

<bean id="role" class="com.wbg.springxmlbean.entity.Role">
    <property name="id" value="1"/>
    <property name="roleName" value="高级工程师"/>
    <property name="note" value="重要人员"/>
</bean>

以上就是一个由 xml 定义的配置元数据。

2.1.2 BeanDefinition 与 BeanDefinitionReader

在 spring 中,无论是那种配置元数据,最终都会转换为BeanDefinition,由 BeanDefinition 形容要生成并被援用的对象,能够了解为 BeanDefinition 就是 bean 的生成模板,或者是 bean 的说明书,依照 BeanDefinition 生成 bean。

而将配置元数据转换为 BeanDefinition 的工作就是由 BeanDefinitionReader 实现的,对于不同的的配置元数据有不同的 Reader 实现对应的工作,例如有 XmlBeanDefinitionReader 读取 xml 配置信息,PropertiesBeanDefinitionReader读取 properties 配置信息,AnnotatedBeanDefinitionReader读取注解的配置信息。

BeanDefinitionReader 的作用就是将磁盘上的文件信息或注解信息转化为内存中用于形容 bean 的 BeanDefinition。

2.1.3 BeanFactoryPostProcessor

BeanFactoryPostProcessor 是容器启动阶段 Spring 提供的一个扩大点,次要负责对注册到 BeanDefinitionRegistry 中的一个个的 BeanDefinition 进行肯定水平上的批改与替换。例如咱们的配置元信息中有些可能会批改的配置信息散落到各处,不够灵便,批改相应配置的时候比拟麻烦,这时咱们能够应用占位符的形式来配置。例如配置 Jdbc 的 DataSource 连贯的时候能够这样配置:

<bean id="dataSource"  
    class="org.apache.commons.dbcp.BasicDataSource"  
    destroy-method="close">  
    <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
    <property name="maxActive" value="${jdbc.maxActive}"></property>  
    <property name="maxWait" value="${jdbc.maxWait}"></property>  
    <property name="minIdle" value="${jdbc.minIdle}"></property>  
  
    <property name="driverClassName"  
        value="${jdbc.driverClassName}">  
    </property>  
    <property name="url" value="${jdbc.url}"></property>  
  
    <property name="username" value="${jdbc.username}"></property>  
    <property name="password" value="${jdbc.password}"></property>  
</bean> 

BeanFactoryPostProcessor 就会对注册到 BeanDefinitionRegistry 中的 BeanDefinition 做最初的批改,替换 $ 占位符为配置文件中的实在的数据。

2.1.4 BeanDefinitionRegistry

一个存储 BeanDefinition 的中央,存储形式为 KV 值,key 为 beanName,value 为 BeanDefinition。

2.1.5 容器启动阶段

容器的启动阶段绝对比较简单,首先会将存在于各处的磁盘上的配置元信息由各自的 Reader 读取到内存之中,转换成 BeanDefinition,而后注册到BeanDefinationRegistry 之中,最初由 BeanFactoryPostProcessor 进行批改与替换。

2.1.6 BeanFactory 与 FactoryBean

BeanFactory 与 FactoryBean 的名字很像,然而的确两个不同的货色。

依据命名规定来看,BeanFactory 是一个 Factory,也就是一个寄存 bean 的工厂,在创立 bean 实现后放到其中,应用是从其中获取。

而 FactoryBean 则是一个 bean,只不过与不同的的 bean 不同的是他不仅能够创立自身类型的 bean,也能够相似于 Factory 一样创立一层有包装的新的 bean。这个 Bean 能够返回一个新的类型的 bean,在返回之前也能够对其进行加工。

@Component
class FactoryBeanDemo implements FactoryBean<Student>{

    @Override
    public Student getObject() {return new Student();
    }

    @Override
    public Class<?> getObjectType() {return Student.class;}
}

创立一个 FactoryBean 只须要实现其接口,并实现其中的两个办法。当咱们获取 FactoryBean 时,会返回其中 getObject()办法返回的对象。而如果想要获取 FactoryBean 自身,只须要在 bean name 前加一个 ”&” 符号即可。

@Resource()
private Object factoryBeanDemo;

@GetMapping("/getStu")
private String getBean(){System.out.println(factoryBeanDemo.getClass());
    return stu2.getName();}
// 输入后果
class com.example.demo.domain.Student

能够看到获取到的是 Student 类型。

class com.example.demo.spring.FactoryBeanDemo

将获取 bean 名称假“&”符号:

@Resource(name = "&factoryBeanDemo")
private Object factoryBeanDemo;
class com.example.demo.spring.FactoryBeanDemo

能够看到获取到的对象变成了 FactoryBeanDemo 自身。

2.2 Bean 注入流程

在容器启动阶段,曾经实现了 bean 的注册。如果该对象是配置成懒加载的形式,那么直到咱们向 Spring 要依赖对象实例之前,其都是以 BeanDefinitionRegistry 中的一个个的 BeanDefinition 的模式存在,也就是 Spring 只有在咱们第一次依赖对象的时候才开启相应对象的实例化阶段。而如果咱们不是抉择懒加载的形式,容器启动阶段实现之后,其中有一个步骤 finishBeanFactoryInitialization(),在这一步将立刻启动 Bean 实例化阶段,通过隐式的调用所有依赖对象的 getBean 办法来实例化所有配置的 Bean,实现类的加载。

doGetBean():获取并返回 bean

doGetBean()的次要流程有两个:

  • 尝试从缓存中获取 bean,如果获取到间接返回。
  • 如果没有获取到则尝试加载 bean。
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {String beanName = transformedBeanName(name);
   Object beanInstance;

   // Eagerly check singleton cache for manually registered singletons.
   // 1、查问缓存中是否存在,存在的话间接返回
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean'" + beanName +
                  "'that is not fully initialized yet - a consequence of a circular reference");
         }
         else {logger.trace("Returning cached instance of singleton bean'" + beanName + "'");
         }
      }
      // 依据缓存中的 bean 获取实例,次要是检测如果是 FactoryBean 类型,则获取其外部的 getObject()的 bean。(须要先理解 FactoryBean 的作用)beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   //2、不存在则创立 bean
   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      // 2.1 尝试从父类的 Factory 加载 bean
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
         }
         else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
         else {return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }

      if (!typeCheckOnly) {markBeanAsCreated(beanName);
      }

      StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
            .tag("beanName", name);
      try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);
         }
         /*
         * 2.2 获取 RootBeanDefinition:首先会依据 beanName 获取 BeanDefinition,而后将 BeanDefinition 转换为 RootBeanDefinition
         * BeanDefinition 接口的实现类有很多,通过不同形式注册到 BeanDefinitionRegistry 中的 BeanDefinition 的类型可能都不太雷同。最终,在通过 BeanDefinition 来创立 bean 的实例时,通常都会调用 getMergedBeanDefinition 来获取到一个 RootBeanDefinition。所以,RootBeanDefinition 实质上是 Spring 运行时对立的 BeanDefinition 视图。* */
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         // 2.3 初始化依赖的 bean
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between'" + beanName + "'and'" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {getBean(dep);
               }
               catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'"+ beanName +"' depends on missing bean '"+ dep +"'", ex);
               }
            }
         }

         // Create bean instance.
         // 2.4 创立实例
         if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {
               try {
                  // 返回真正的 bean
                  return createBean(beanName, mbd, args);
               }
               catch (BeansException ex) {
                  // Explicitly remove instance from singleton cache: It might have been put there
                  // eagerly by the creation process, to allow for circular reference resolution.
                  // Also remove any beans that received a temporary reference to the bean.
                  destroySingleton(beanName);
                  throw ex;
               }
            });
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }
   }

   return adaptBeanInstance(name, beanInstance, requiredType);
}

2.2.1 mbd = getMergedLocalBeanDefinition(beanName)获取 BeanDefinition

RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

BeanDefinition 接口的实现类有很多,通过不同形式注册到 BeanDefinitionRegistry 中的 BeanDefinition 的类型可能都不太雷同。
最终,在通过 BeanDefinition 来创立 bean 的实例时,通常都会调用 getMergedBeanDefinition 来获取到一个 RootBeanDefinition。所以,RootBeanDefinition 实质上是 Spring 运行时对立的 BeanDefinition 视图。

此处就是将各种 BeanDefinition 对立转换为 spring 能辨认的 RootBeanDefinition。

2.2.2 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 获取创立好的对象

sharedInstance = getSingleton(beanName, () -> {
   try {
      // 返回真正的 bean
      return createBean(beanName, mbd, args);
   }
   catch (BeansException ex) {
      // Explicitly remove instance from singleton cache: It might have been put there
      // eagerly by the creation process, to allow for circular reference resolution.
      // Also remove any beans that received a temporary reference to the bean.
      destroySingleton(beanName);
      throw ex;
   }
});

getSingleton() 办法中获取创立好的对象

// 获取 singletonFactory 返回的后果
singletonObject = singletonFactory.getObject();

getSingleton()办法中最次要的一次调用也就是从 singletonFactory 中获取对象,而获取对象的后果就是下面代码中传入的匿名工厂返回的后果,也就是 createBean(beanName, mbd, args)

2.2.3 createBean(beanName, mbd, args) 创立 bean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean'" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   // 1. 解析 bean class
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   // 2. 筹备笼罩的办法
   try {mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      // 3. 尝试返回代理创立的 Bean,这个作用就是查找 bean 中所有实现前置和后置处理器的接口,有没有手工创立而后返回的,代替了 spring 的创立 bean 的流程
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {return bean;}
   }
   catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      //4. 真正创立 bean
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean'" + beanName + "'");
      }
      return beanInstance;
   }
   catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
   }
}

创立 bean 次要有以下几步:

  1. 解析 bean 的 class 文件,为前面的依据 class 文件通过反射创建对象做筹备。
  2. 预处理 bean 的 Override 属性,预处理的形式也比较简单,就是在办法 prepareMethodOverride 中判断一下,如果 lookup-method 标签或者 replaced-method 标签中配置了 bean 中须要笼罩的办法,就将 MethodOverride 中的 overload 属性值设置为 false。
  3. 尝试通过反射获取被代理的 bean。
  4. 真正创立 bean 的过程

2.2.4 Object beanInstance = doCreateBean(beanName, mbdToUse, args) 开始创立 bean

以上流程都是获取 bean 前的流程或获取 bean 的筹备,doCreateBean 是真正的创立并填充 bean 的流程(去掉了一些不重要的代码)。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      //1. 通过反射创立实例化对象,并将其放入 wraaper 中。wraaper 能够了解为 bean 的包装对象,外面是 bean 实例的,还有一些其余 bean 的属性方便使用
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}

   // Allow post-processors to modify the merged bean definition.
   //2. 容许后处理处理器批改合并后的 bean 定义,这里只是解析这些 @Autowired @Value @Resource @PostConstruct 等这些注解,并没有产生理论属性注入的动作
   synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {
         try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         mbd.postProcessed = true;
      }
   }

   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   //3. 是否须要提前曝光,用来解决循环依赖时应用
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean'" + beanName +
               "'to allow for resolving potential circular references");
      }
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   //4. 将实例化实现成的 bean 填充属性
   populateBean(beanName, mbd, instanceWrapper);
   //5. 调用初始化办法,例如 init-method
   exposedObject = initializeBean(beanName, exposedObject, mbd);
  
  
   //6. 循环依赖查看
   if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);
               }
            }
         }
      }
   }

   // Register bean as disposable.
   //7. 注册 bean
   try {registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

从上述流程中能够看到,咱们创立一个 bean 次要有以下几个流程:

  1. 首先通过 class 依据反射创建对象,此时该对象的所有的属性都为空,能够了解为咱们 new 出的空属性对象。
  2. 解析 @Autowired @Value @Resource @PostConstruct 这些注解,但并没有产生属性注入的行为。
  3. 是否须要提前曝光,用来解决循环依赖时应用,次要作用是如果须要代理会返回代理对象,如果不须要代理,返回后面创立的对象
  4. 将第一步实例化实现的空属性对象填充属性,其中如果该 bean 依赖了其余 bean,也会在此步骤将依赖的 bean 拆卸,如果 bean 曾经被创立,则间接属性注入,如果不存在,则创立 bean,创立形式跟本 bean 雷同,能够了解为递归。
  5. 将实例化实现的 bean 对象初始化,次要查看 bean 是否实现了一些前置或后置或初始化的办法,如果是的话就执行。
  6. 循环依赖查看。
  7. 依据 scope 注册 bean。

能够看到,通过以上的几个步骤,咱们就获取到了一个实例 bean。

其中最重要的三个办法:

  1. 实例化 bean
  2. 拆卸属性
  3. 初始化 bean

2.2.5 总结

总结来说,创立 bean 的流程就是先依据反射获取对象,而后填充对象的属性,初始化,最初将 bean 注册。

2.3 创立 bean 流程深刻了解

上文咱们只粗略的解说了创立 bean 的过程,并没有深刻的查看源码是如何实现的,例如通过反射获取对象是怎么获取的,填充属性是如何填充的,下文将具体论述 2.2.5 过程中在源码层面是如何构建的。

2.3.1 instanceWrapper = createBeanInstance(beanName, mbd, args) 获取实例化对象

该办法通过反射获取实例化的空属性对象。

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

   //1.2 确认 public 权限
   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());
   }

   //2. 如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化,因为反射获取对象的效率比拟低
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);
   }

   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) {
         /*
         * 3. 如果 args 为空且办法曾经被 resolved,则会间接抉择对应的构造方法
         * mbd.resolvedConstructorOrFactoryMethod 的赋值在下方【1】【2】的代码中赋值
         * */
         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?
   //4. 主动拆卸的构造方法
   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?
   //5. 是否有首选构造方法
   ctors = mbd.getPreferredConstructors();
   if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);
   }

   // No special handling: simply use no-arg constructor.
   //6. 通过默认的无参构造函数
   return instantiateBean(beanName, mbd);
}
  1. 首先解析 class 文件与确认 public 权限。
  2. 如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化,因为反射获取对象的效率比拟低。
  3. 如果 args 为空且应用那个构造函数曾经被确定了,则进行标记,后续间接抉择应用那种构造方法。
  4. 如果 args 不为空或没有被解析过,则抉择应用那种构造方法来结构实例化的对象:

Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);

抉择 AutowiredAnnotationBeanPostProcessor 实现类:

其中重要的代码已贴出:

//1. 遍历所有的构造方法
for (Constructor<?> candidate : rawCandidates) {if (!candidate.isSynthetic()) {nonSyntheticConstructors++;}
   else if (primaryConstructor != null) {continue;}
   //2. 查看以后构造方法是否有 @Autowired 注解
   MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
   if (ann == null) {Class<?> userClass = ClassUtils.getUserClass(beanClass);
      if (userClass != beanClass) {
         try {
            Constructor<?> superCtor =
                  userClass.getDeclaredConstructor(candidate.getParameterTypes());
            ann = findAutowiredAnnotation(superCtor);
         }
         catch (NoSuchMethodException ex) {// Simply proceed, no equivalent superclass constructor found...}
      }
   }
   //3. 如果有 @Autowired 注解
   if (ann != null) {
      //4. 如果曾经有一个 @Autowired 注解,则阐明存在多个 @Autowired 注解,则抛出异样
      if (requiredConstructor != null) {
         throw new BeanCreationException(beanName,
               "Invalid autowire-marked constructor:" + candidate +
               ". Found constructor with'required'Autowired annotation already:" +
               requiredConstructor);
      }
      boolean required = determineRequiredStatus(ann);
      if (required) {if (!candidates.isEmpty()) {
            throw new BeanCreationException(beanName,
                  "Invalid autowire-marked constructors:" + candidates +
                  ". Found constructor with'required'Autowired annotation:" +
                  candidate);
         }
         requiredConstructor = candidate;
      }
      candidates.add(candidate);
   }
   // 5 无参构造函数
   else if (candidate.getParameterCount() == 0) {
      // 将其设置为默认构造函数
      defaultConstructor = candidate;
   }
}
// 对下面的处理过程进行判断
//6.1 先查看是否有 @Autowired 注解
if (!candidates.isEmpty()) {
   // Add default constructor to list of optional constructors, as fallback.
   if (requiredConstructor == null) {if (defaultConstructor != null) {candidates.add(defaultConstructor);
      }
      else if (candidates.size() == 1 && logger.isInfoEnabled()) {
         logger.info("Inconsistent constructor declaration on bean with name'" + beanName +
               "': single autowire-marked constructor flagged as optional -" +
               "this constructor is effectively required since there is no" +
               "default constructor to fall back to:" + candidates.get(0));
      }
   }
  // 返回 @Autowired 注解的构造方法
   candidateConstructors = candidates.toArray(new Constructor<?>[0]);
}
//6.2 如果只有一个有参构造函数,则返回该有参函数
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
}
//6.3 对于非 Kotlin 类只会返回 null,所以这里不会进入
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
      defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
}
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {candidateConstructors = new Constructor<?>[] {primaryConstructor};
}
else {
   //6.4 对于不能辨认的场景会进入到这里,例如有多个构造函数然而并没有指定 @Autowired 注解或者没有构造函数(java 会帮咱们生成一个无参的构造函数),返回 null
   candidateConstructors = new Constructor<?>[0];
}

2- 5 步会对所有的构造函数进行查看,并在查看完进行标记,并会在第 6 步对标记的后果进行返回,依照 ifelse 判断程序次要分为以下几种状况:

  • 如果有 @Autowired 注解的办法则返回该构造方法
  • 如果只有一个有参构造函数则会返回该有参构造函数
  • 对于不能辨认的场景会进入到这里,例如有多个构造函数然而并没有指定 @Autowired 注解或者没有构造函数(java 会帮咱们生成一个无参的构造函数)会返回 null

在获取到须要的构造函数后,会进行标记,下次不必再次解析能够间接选用那个构造函数,即上文的第 4 步

  1. 是否有首选的构造函数
  2. 如果都没有的话,通过默认的无参构造函数创建对象。

咱们查看代码发现,无论第 4 步返回什么后果,最终会执行以下两个办法:

autowireConstructor()与 instantiateBean()

两者都会调用

instantiate()办法

最终都会执行以下这个办法

BeanUtils.instantiateClass(constructorToUse)

也就是如下的代码

for (int i = 0 ; i < args.length; i++) {if (args[i] == null) {Class<?> parameterType = parameterTypes[i];
      argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
   }
   else {argsWithDefaultValues[i] = args[i];
   }
}
return ctor.newInstance(argsWithDefaultValues);

其中最重要的一句:

return ctor.newInstance(argsWithDefaultValues);

能够发现,也就是这里通过反射的形式创立了一个空属性对象,并一层层返回,直到前面的属性拆卸等过程,能够说这里就是 bean 加载过程的源头。

2.3.2 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName) 解析各种注解

该办法次要解析该 bean 所相干的注解,例如属性有 @Resource,bean 中 @PostConstruct 注解都会被解析。

for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}

processor 次要有两个实现类:

  1. AutowiredAnnotationBeanPostProcessor 解决 @Autowired 和 @Value 注解 bean 定义信息
  2. CommonAnnotationBeanPostProcessor 解决 @Resource、@PostConstruct、@PreDestroy 注解的 bean 定义信息

这里须要留神的是,该办法只是会解析并不会真正的进行注入,因为学习意义不大,并不在赘述。

2.3.3 populateBean(beanName, mbd, instanceWrapper) 对实例化实现的 bean 进行属性注入

// 遍历所有的属性
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
   // 对属性进行装填
   PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
   if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      }
      pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
      if (pvsToUse == null) {return;}
   }
   pvs = pvsToUse;
}

其中 bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName)有几个实现办法,比拟重要的是:

  1. AutowiredAnnotationBeanPostProcessor,次要拆卸属性是 @Autowired 与 @Value 的属性
  2. CommonAnnotationBeanPostProcessor,次要拆卸属性是 @Resource 的属性

两者最终都会进入如下办法:

// 判断要注入的是属性还是办法
if (this.isField) {Field field = (Field) this.member;
   ReflectionUtils.makeAccessible(field);
   // 如果是属性的话则间接注入
   field.set(target, getResourceToInject(target, requestingBeanName));
}
else {if (checkPropertySkipping(pvs)) {return;}
   try {Method method = (Method) this.member;
      ReflectionUtils.makeAccessible(method);
      // 否则通过反射注入
      method.invoke(target, getResourceToInject(target, requestingBeanName));
   }
   catch (InvocationTargetException ex) {throw ex.getTargetException();
   }
}

了解起来比较简单,判断是办法注入还是属性注入,在注入时注入的对象为:

getResourceToInject(target, requestingBeanName)

找到 ResourceElement 的实现办法中 getResource() 办法:

返回了 autowireResource(this.resourceFactory, element, requestingBeanName)

if (factory instanceof AutowireCapableBeanFactory) {AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
   DependencyDescriptor descriptor = element.getDependencyDescriptor();
   if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {autowiredBeanNames = new LinkedHashSet<>();
      resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
      if (resource == null) {throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
      }
   }
   else {resource = beanFactory.resolveBeanByName(name, descriptor);
      autowiredBeanNames = Collections.singleton(name);
   }
}
else {resource = factory.getBean(name, element.lookupType);
   autowiredBeanNames = Collections.singleton(name);
}

在这个办法中,无论是 if 还是 else,最终都会调用

getBean(name, element.lookupType)

也就是咱们 bean 注入的入口,这个过程很像递归,在咱们创立 bean 时,如果发现咱们有依赖的其余 bean,那么就会去创立依赖的 bean,如果依赖的 bean 还有其依赖的属性则又会去创立被依赖的属性,只到最终全副创立实现,返回一开始想要创立的 bean。

2.3.4 exposedObject = initializeBean(beanName, exposedObject, mbd)初始化 bean

在该办法中,会对曾经填充过属性的 bean 进行初始化:

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
   // 对 bean 的前置解决,其中 @PostConstruct 就在此步骤中
   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
   // 调用初始化办法如果 bean 实现了 InitializingBean 接口,则先执行 InitializingBean 接口的 afterPropertiesSet 办法,而后执行 xml 或注解设置的 init-method 办法。invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
   throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),
         beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
   // 对 bean 进行后置解决,对象的代理产生在此步骤中
   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

在初始化 bean 的时候,次要分为三个局部,别离是applyBeanPostProcessorsBeforeInitialization、invokeInitMethods、applyBeanPostProcessorsAfterInitialization,别离对应于初始化的前置解决、自定义 init 办法、后置解决。

applyBeanPostProcessorsBeforeInitialization、applyBeanPostProcessorsAfterInitialization两个办法的大略逻辑就是获取获取所有实现其接口的类,而后执行其中被笼罩的办法。

罕用的注解执行程序如下:

  1. @PostConstruct 注解润饰的办法
  2. InitializingBean 接口的 afterPropertiesSet()办法
  3. init-method 指定的办法
  4. @PreDestroy 注解润饰的办法
  5. DisposableBean 接口的 destroy()办法
  6. destory-method 指定的办法

并且在代码中能够看到,前置解决与后置解决都能够扭转 bean。

在容器启动阶段咱们讲到 BeanFactoryPostProcessor,这里咱们讲到 BeanPostProcessor,那么 BeanFactoryPostProcessor 和 BeanPostProcessor 有什么区别呢?

BeanFactoryPostProcessor 存在于容器启动阶段,而 BeanPostProcessor 存在于对象实例化阶段,BeanFactoryPostProcessor 关注对象被创立之前那些配置的批改,而 BeanPostProcessor 阶段关注对象曾经被创立之后的性能加强,替换等操作,这样就很容易辨别了。
BeanPostProcessor 与 BeanFactoryPostProcessor 都是 Spring 在 Bean 生产过程中强有力的扩大点。Spring 中驰名的 AOP(面向切面编程),其实就是依赖 BeanPostProcessor 对 Bean 对象性能加强的。

BeanFactoryPostProcessor 次要用于解决实例化之前,对实例的属性进行拓展,而 BeanPostProcessor 是在实例化之后对对象做的拓展。

2.4 总结

用简略的话形容一下,创立一个 bean 的过程大略包含三局部:

  1. 通过反射实例化 bean
  2. 属性拆卸以及填充
  3. 初始化,包含 init-method、以及其前后三个步骤。其中 AOP 加强就是产生在初始化之后的 applyBeanPostProcessorsAfterInitialization 的步骤中。

通过以上的步骤,就能够取得咱们能够失常应用的一个 bean。

正文完
 0