0源码基础学习Spring源码系列(一)——Bean注入流程

作者:京东科技 韩国凯

通过本文,读者可以0源码基础的初步学习spring源码,并能够举一反三从此进入源码世界的大米!
由于是第一次阅读源码,文章之中难免存在一些问题,还望包涵指正!

一、 @Autowired与@Resource的区别

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

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

1//创建接口 2interface StuService{ 3 String getName(); 4} 5 6@Service 7//Stu2实现接口并注册bean 8class Stu2 implements StuService{ 9 @Override 10 public String getName() { 11 return "stu2"; 12 } 13} 14 15@Service 16//Stu3实现接口并注册bean 17class Stu3 implements StuService{ 18 @Override 19 public String getName() { 20 return "stu3"; 21 } 22}

1.1 @Autowired

那么此时如果我们对 StuService注入, @Autowired可以选择注入的类型就有两个,分别是 Stu2与 Stu3

需要注意的是,类型有很多种选择:

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

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

1@Component 2class SessionUtil{ 3 public String getSession(){ 4 return "session"; 5 } 6}

只有一个类,直接注册bean,使用时可以任意选择

1@Autowired 2SessionUtil sessionUtil;

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

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

例如上述 StuService有多个实现类,每个实现类都注册了bean,因此@Autowired可以选择的类型就有两个。

1@Autowired 2StuService 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时,可以直接注册
1@Autowired 2SessionUtil sessionUtil;
  1. 当有多个bean注册时,如果未指定名称,则bean name为类名首字母小写,指定了bean名称则注册名称为该名称。

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

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

1@Bean() 2public Student getStudent(){ 3 Student student = new Student(); 4 student.setName("bob"); 5 student.setId(26); 6 return student; 7}

此时该bean名称为 getStudent

同样,我们也可以注册bean时自定义bean名称

1@Bean("stu1") 2public Student getStudent(){ 3 Student student = new Student(); 4 student.setName("bob"); 5 student.setId(26); 6 return student; 7} 8 9@Service("stu2") 10class Stu2 implements StuService{ 11 @Override 12 public String getName() { 13 return "stu2"; 14 } 15} 16 17@Component("stu3") 18class Stu3 implements StuService{ 19 @Override 20 public String getName() { 21 return "stu3"; 22 } 23}

在引用时指定bean:

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

1.3 @Autowired

当我们使用@Resource时,会根据名称也就是 stu2去查询,此时bean名称只有一个,查到返回

1@Resource 2private 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的信息。

1<bean id="role" class="com.wbg.springxmlbean.entity.Role"> 2 <property name="id" value="1"/> 3 <property name="roleName" value="高级工程师"/> 4 <property name="note" value="重要人员"/> 5</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连接的时候可以这样配置:

1<bean id="dataSource" 2 class="org.apache.commons.dbcp.BasicDataSource" 3 destroy-method="close"> 4 <property name="maxIdle" value="${jdbc.maxIdle}"></property> 5 <property name="maxActive" value="${jdbc.maxActive}"></property> 6 <property name="maxWait" value="${jdbc.maxWait}"></property> 7 <property name="minIdle" value="${jdbc.minIdle}"></property> 8 9 <property name="driverClassName" 10 value="${jdbc.driverClassName}"> 11 </property> 12 <property name="url" value="${jdbc.url}"></property> 13 14 <property name="username" value="${jdbc.username}"></property> 15 <property name="password" value="${jdbc.password}"></property> 16</bean>

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

2.1.4 BeanDefinitionRegistry

一个存储BeanDefinition的地方,存储方式为KV值,key为beanName,value为BeanDefinition。

2.1.5 容器启动阶段

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

img

2.1.6 BeanFactory与FactoryBean

BeanFactory与FactoryBean的名字很像,但是确实两个不同的东西。

根据命名规则来看,BeanFactory是一个Factory,也就是一个存放bean的工厂,在创建bean完成后放到其中,使用是从其中获取。

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

1@Component 2class FactoryBeanDemo implements FactoryBean<Student>{ 3 4 @Override 5 public Student getObject() { 6 return new Student(); 7 } 8 9 @Override 10 public Class<?> getObjectType() { 11 return Student.class; 12 } 13}

创建一个FactoryBean只需要实现其接口,并实现其中的两个方法。当我们获取FactoryBean时,会返回其中 getObject()方法返回的对象。而如果想要获取FactoryBean本身,只需要在bean name前加一个"&"符号即可。

1@Resource() 2private Object factoryBeanDemo; 3 4@GetMapping("/getStu") 5private String getBean(){ 6 7 System.out.println(factoryBeanDemo.getClass()); 8 return stu2.getName(); 9}
1//输出结果 2class com.example.demo.domain.Student

可以看到获取到的是Student类型。

class com.example.demo.spring.FactoryBeanDemo

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

1@Resource(name = "&factoryBeanDemo") 2private 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。
1protected <T> T doGetBean( 2 String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) 3 throws BeansException { 4 5 String beanName = transformedBeanName(name); 6 Object beanInstance; 7 8 // Eagerly check singleton cache for manually registered singletons. 9 // 1、查询缓存中是否存在,存在的话直接返回 10 Object sharedInstance = getSingleton(beanName); 11 if (sharedInstance != null && args == null) { 12 if (logger.isTraceEnabled()) { 13 if (isSingletonCurrentlyInCreation(beanName)) { 14 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + 15 "' that is not fully initialized yet - a consequence of a circular reference"); 16 } 17 else { 18 logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); 19 } 20 } 21 // 根据缓存中的bean获取实例,主要是检测如果是FactoryBean类型,则获取其内部的getObject()的bean。(需要先了解FactoryBean的作用) 22 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); 23 } 24 25 //2、不存在则创建bean 26 else { 27 // Fail if we're already creating this bean instance: 28 // We're assumably within a circular reference. 29 if (isPrototypeCurrentlyInCreation(beanName)) { 30 throw new BeanCurrentlyInCreationException(beanName); 31 } 32 33 // Check if bean definition exists in this factory. 34 // 2.1 尝试从父类的Factory加载bean 35 BeanFactory parentBeanFactory = getParentBeanFactory(); 36 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 37 // Not found -> check parent. 38 String nameToLookup = originalBeanName(name); 39 if (parentBeanFactory instanceof AbstractBeanFactory) { 40 return ((AbstractBeanFactory) parentBeanFactory).doGetBean( 41 nameToLookup, requiredType, args, typeCheckOnly); 42 } 43 else if (args != null) { 44 // Delegation to parent with explicit args. 45 return (T) parentBeanFactory.getBean(nameToLookup, args); 46 } 47 else if (requiredType != null) { 48 // No args -> delegate to standard getBean method. 49 return parentBeanFactory.getBean(nameToLookup, requiredType); 50 } 51 else { 52 return (T) parentBeanFactory.getBean(nameToLookup); 53 } 54 } 55 56 if (!typeCheckOnly) { 57 markBeanAsCreated(beanName); 58 } 59 60 StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate") 61 .tag("beanName", name); 62 try { 63 if (requiredType != null) { 64 beanCreation.tag("beanType", requiredType::toString); 65 } 66 /* 67 * 2.2 获取RootBeanDefinition:首先会根据beanName获取BeanDefinition,然后将BeanDefinition转换为RootBeanDefinition 68 * BeanDefinition 接口的实现类有很多,通过不同方式注册到 BeanDefinitionRegistry 中的 BeanDefinition 的类型可能都不太相同。 69 最终,在通过 BeanDefinition 来创建 bean 的实例时,通常都会调用 getMergedBeanDefinition 来获取到一个 RootBeanDefinition。 70 所以,RootBeanDefinition 本质上是 Spring 运行时统一的 BeanDefinition 视图。 71 * */ 72 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 73 checkMergedBeanDefinition(mbd, beanName, args); 74 75 // Guarantee initialization of beans that the current bean depends on. 76 // 2.3 初始化依赖的bean 77 String[] dependsOn = mbd.getDependsOn(); 78 if (dependsOn != null) { 79 for (String dep : dependsOn) { 80 if (isDependent(beanName, dep)) { 81 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 82 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); 83 } 84 registerDependentBean(dep, beanName); 85 try { 86 getBean(dep); 87 } 88 catch (NoSuchBeanDefinitionException ex) { 89 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 90 "'" + beanName + "' depends on missing bean '" + dep + "'", ex); 91 } 92 } 93 } 94 95 // Create bean instance. 96 // 2.4 创建实例 97 if (mbd.isSingleton()) { 98 sharedInstance = getSingleton(beanName, () -> { 99 try { 100 //返回真正的bean 101 return createBean(beanName, mbd, args); 102 } 103 catch (BeansException ex) { 104 // Explicitly remove instance from singleton cache: It might have been put there 105 // eagerly by the creation process, to allow for circular reference resolution. 106 // Also remove any beans that received a temporary reference to the bean. 107 destroySingleton(beanName); 108 throw ex; 109 } 110 }); 111 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 112 } 113 } 114 115 return adaptBeanInstance(name, beanInstance, requiredType); 116}

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) 获取创建好的对象

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

getSingleton()方法中获取创建好的对象

1//获取singletonFactory返回的结果 2singletonObject = singletonFactory.getObject();

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

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

1protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 2 throws BeanCreationException { 3 4 if (logger.isTraceEnabled()) { 5 logger.trace("Creating instance of bean '" + beanName + "'"); 6 } 7 RootBeanDefinition mbdToUse = mbd; 8 9 // Make sure bean class is actually resolved at this point, and 10 // clone the bean definition in case of a dynamically resolved Class 11 // which cannot be stored in the shared merged bean definition. 12 // 1.解析bean class 13 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); 14 if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { 15 mbdToUse = new RootBeanDefinition(mbd); 16 mbdToUse.setBeanClass(resolvedClass); 17 } 18 19 // Prepare method overrides. 20 // 2.准备覆盖的方法 21 try { 22 mbdToUse.prepareMethodOverrides(); 23 } 24 catch (BeanDefinitionValidationException ex) { 25 throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), 26 beanName, "Validation of method overrides failed", ex); 27 } 28 29 try { 30 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 31 // 3.尝试返回代理创建的Bean,这个作用就是查找bean中所有实现前置和后置处理器的接口,有没有手工创建然后返回的,代替了spring的创建bean的流程 32 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 33 if (bean != null) { 34 return bean; 35 } 36 } 37 catch (Throwable ex) { 38 throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, 39 "BeanPostProcessor before instantiation of bean failed", ex); 40 } 41 42 try { 43 //4.真正创建bean 44 Object beanInstance = doCreateBean(beanName, mbdToUse, args); 45 if (logger.isTraceEnabled()) { 46 logger.trace("Finished creating instance of bean '" + beanName + "'"); 47 } 48 return beanInstance; 49 } 50 catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { 51 // A previously detected exception with proper bean creation context already, 52 // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. 53 throw ex; 54 } 55 catch (Throwable ex) { 56 throw new BeanCreationException( 57 mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); 58 } 59}

创建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的流程(去掉了一些不重要的代码)。

1protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 2 throws BeanCreationException { 3 4 // Instantiate the bean. 5 BeanWrapper instanceWrapper = null; 6 if (mbd.isSingleton()) { 7 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 8 } 9 if (instanceWrapper == null) { 10 //1.通过反射创建实例化对象,并将其放入wraaper中。wraaper可以理解为bean的包装对象,里面是bean实例的,还有一些其他bean的属性方便使用 11 instanceWrapper = createBeanInstance(beanName, mbd, args); 12 } 13 Object bean = instanceWrapper.getWrappedInstance(); 14 Class<?> beanType = instanceWrapper.getWrappedClass(); 15 if (beanType != NullBean.class) { 16 mbd.resolvedTargetType = beanType; 17 } 18 19 // Allow post-processors to modify the merged bean definition. 20 //2.允许后处理处理器修改合并后的bean定义,这里只是解析这些@Autowired @Value @Resource @PostConstruct等这些注解,并没有发生实际属性注入的动作 21 synchronized (mbd.postProcessingLock) { 22 if (!mbd.postProcessed) { 23 try { 24 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 25 } 26 mbd.postProcessed = true; 27 } 28 } 29 30 // Eagerly cache singletons to be able to resolve circular references 31 // even when triggered by lifecycle interfaces like BeanFactoryAware. 32 //3.是否需要提前曝光,用来解决循环依赖时使用 33 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && 34 isSingletonCurrentlyInCreation(beanName)); 35 if (earlySingletonExposure) { 36 if (logger.isTraceEnabled()) { 37 logger.trace("Eagerly caching bean '" + beanName + 38 "' to allow for resolving potential circular references"); 39 } 40 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 41 } 42 43 // Initialize the bean instance. 44 Object exposedObject = bean; 45 //4.将实例化完成成的bean填充属性 46 populateBean(beanName, mbd, instanceWrapper); 47 //5.调用初始化方法,例如 init-method 48 exposedObject = initializeBean(beanName, exposedObject, mbd); 49 50 51 //6.循环依赖检查 52 if (earlySingletonExposure) { 53 Object earlySingletonReference = getSingleton(beanName, false); 54 if (earlySingletonReference != null) { 55 if (exposedObject == bean) { 56 exposedObject = earlySingletonReference; 57 } 58 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { 59 String[] dependentBeans = getDependentBeans(beanName); 60 Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); 61 for (String dependentBean : dependentBeans) { 62 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 63 actualDependentBeans.add(dependentBean); 64 } 65 } 66 } 67 } 68 } 69 70 // Register bean as disposable. 71 //7.注册bean 72 try { 73 registerDisposableBeanIfNecessary(beanName, bean, mbd); 74 } 75 catch (BeanDefinitionValidationException ex) { 76 throw new BeanCreationException( 77 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); 78 } 79 80 return exposedObject; 81}

从上述流程中可以看到,我们创建一个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) 获取实例化对象

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

1protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { 2 // Make sure bean class is actually resolved at this point. 3 //1.1解析class 4 Class<?> beanClass = resolveBeanClass(mbd, beanName); 5 6 //1.2确认public权限 7 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { 8 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 9 "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); 10 } 11 12 //2.如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化,因为反射获取对象的效率比较低 13 Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); 14 if (instanceSupplier != null) { 15 return obtainFromSupplier(instanceSupplier, beanName); 16 } 17 18 if (mbd.getFactoryMethodName() != null) { 19 return instantiateUsingFactoryMethod(beanName, mbd, args); 20 } 21 22 // Shortcut when re-creating the same bean... 23 boolean resolved = false; 24 boolean autowireNecessary = false; 25 if (args == null) { 26 synchronized (mbd.constructorArgumentLock) { 27 /* 28 * 3.如果args为空且方法已经被resolved,则会直接选择对应的构造方法 29 * mbd.resolvedConstructorOrFactoryMethod的赋值在下方【1】【2】的代码中赋值 30 * */ 31 if (mbd.resolvedConstructorOrFactoryMethod != null) { 32 resolved = true; 33 autowireNecessary = mbd.constructorArgumentsResolved; 34 } 35 } 36 } 37 if (resolved) { 38 if (autowireNecessary) { 39 return autowireConstructor(beanName, mbd, null, null); 40 } 41 else { 42 return instantiateBean(beanName, mbd); 43 } 44 } 45 46 // Candidate constructors for autowiring? 47 //4.自动装配的构造方法 48 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); 49 if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || 50 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { 51 return autowireConstructor(beanName, mbd, ctors, args); 52 } 53 54 // Preferred constructors for default construction? 55 //5.是否有首选构造方法 56 ctors = mbd.getPreferredConstructors(); 57 if (ctors != null) { 58 return autowireConstructor(beanName, mbd, ctors, null); 59 } 60 61 // No special handling: simply use no-arg constructor. 62 //6.通过默认的无参构造函数 63 return instantiateBean(beanName, mbd); 64}
  1. 首先解析class文件与确认public权限。
  2. 如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化,因为反射获取对象的效率比较低。
  3. 如果args为空且使用那个构造函数已经被确定了,则进行标记,后续直接选择使用那种构造方法。
  4. 如果args不为空或没有被解析过,则选择使用那种构造方法来构造实例化的对象:

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

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

选择AutowiredAnnotationBeanPostProcessor实现类:

其中重要的代码已贴出:

1//1.遍历所有的构造方法 2for (Constructor<?> candidate : rawCandidates) { 3 if (!candidate.isSynthetic()) { 4 nonSyntheticConstructors++; 5 } 6 else if (primaryConstructor != null) { 7 continue; 8 } 9 //2.查看当前构造方法是否有@Autowired注解 10 MergedAnnotation<?> ann = findAutowiredAnnotation(candidate); 11 if (ann == null) { 12 Class<?> userClass = ClassUtils.getUserClass(beanClass); 13 if (userClass != beanClass) { 14 try { 15 Constructor<?> superCtor = 16 userClass.getDeclaredConstructor(candidate.getParameterTypes()); 17 ann = findAutowiredAnnotation(superCtor); 18 } 19 catch (NoSuchMethodException ex) { 20 // Simply proceed, no equivalent superclass constructor found... 21 } 22 } 23 } 24 //3.如果有@Autowired注解 25 if (ann != null) { 26 //4.如果已经有一个@Autowired注解,则说明存在多个@Autowired注解,则抛出异常 27 if (requiredConstructor != null) { 28 throw new BeanCreationException(beanName, 29 "Invalid autowire-marked constructor: " + candidate + 30 ". Found constructor with 'required' Autowired annotation already: " + 31 requiredConstructor); 32 } 33 boolean required = determineRequiredStatus(ann); 34 if (required) { 35 if (!candidates.isEmpty()) { 36 throw new BeanCreationException(beanName, 37 "Invalid autowire-marked constructors: " + candidates + 38 ". Found constructor with 'required' Autowired annotation: " + 39 candidate); 40 } 41 requiredConstructor = candidate; 42 } 43 candidates.add(candidate); 44 } 45 //5无参构造函数 46 else if (candidate.getParameterCount() == 0) { 47 //将其设置为默认构造函数 48 defaultConstructor = candidate; 49 } 50} 51//对上面的处理过程进行判断 52//6.1先检查是否有@Autowired注解 53if (!candidates.isEmpty()) { 54 // Add default constructor to list of optional constructors, as fallback. 55 if (requiredConstructor == null) { 56 if (defaultConstructor != null) { 57 candidates.add(defaultConstructor); 58 } 59 else if (candidates.size() == 1 && logger.isInfoEnabled()) { 60 logger.info("Inconsistent constructor declaration on bean with name '" + beanName + 61 "': single autowire-marked constructor flagged as optional - " + 62 "this constructor is effectively required since there is no " + 63 "default constructor to fall back to: " + candidates.get(0)); 64 } 65 } 66 //返回@Autowired注解的构造方法 67 candidateConstructors = candidates.toArray(new Constructor<?>[0]); 68} 69//6.2如果只有一个有参构造函数,则返回该有参函数 70else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) { 71 candidateConstructors = new Constructor<?>[] {rawCandidates[0]}; 72} 73//6.3对于非Kotlin类只会返回null,所以这里不会进入 74else if (nonSyntheticConstructors == 2 && primaryConstructor != null && 75 defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) { 76 candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor}; 77} 78else if (nonSyntheticConstructors == 1 && primaryConstructor != null) { 79 candidateConstructors = new Constructor<?>[] {primaryConstructor}; 80} 81else { 82 //6.4对于不能识别的场景会进入到这里,例如有多个构造函数但是并没有指定@Autowired注解或者没有构造函数(java会帮我们生成一个无参的构造函数),返回null 83 candidateConstructors = new Constructor<?>[0]; 84}

2-5步会对所有的构造函数进行检查,并在检查完进行标记,并会在第6步对标记的结果进行返回,按照ifelse判断顺序主要分为以下几种情况:

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

在获取到需要的构造函数后,会进行标记,下次不用再次解析可以直接选用那个构造函数,即上文的第4步

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

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

autowireConstructor()与instantiateBean()

两者都会调用

instantiate()方法

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

BeanUtils.instantiateClass(constructorToUse)

也就是如下的代码

1for (int i = 0 ; i < args.length; i++) { 2 if (args[i] == null) { 3 Class<?> parameterType = parameterTypes[i]; 4 argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null); 5 } 6 else { 7 argsWithDefaultValues[i] = args[i]; 8 } 9} 10return ctor.newInstance(argsWithDefaultValues);

其中最重要的一句:

return ctor.newInstance(argsWithDefaultValues);

可以发现,也就是这里通过反射的方式创建了一个空属性对象,并一层层返回,直到后面的属性装配等过程,可以说这里就是bean加载过程的源头。

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

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

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

processor主要有两个实现类:

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

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

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

1//遍历所有的属性 2for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { 3 //对属性进行装填 4 PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); 5 if (pvsToUse == null) { 6 if (filteredPds == null) { 7 filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); 8 } 9 pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 10 if (pvsToUse == null) { 11 return; 12 } 13 } 14 pvs = pvsToUse; 15}

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

  1. AutowiredAnnotationBeanPostProcessor,主要装配属性是@Autowired与@Value的属性
  2. CommonAnnotationBeanPostProcessor,主要装配属性是@Resource的属性

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

1//判断要注入的是属性还是方法 2if (this.isField) { 3 Field field = (Field) this.member; 4 ReflectionUtils.makeAccessible(field); 5 //如果是属性的话则直接注入 6 field.set(target, getResourceToInject(target, requestingBeanName)); 7} 8else { 9 if (checkPropertySkipping(pvs)) { 10 return; 11 } 12 try { 13 Method method = (Method) this.member; 14 ReflectionUtils.makeAccessible(method); 15 //否则通过反射注入 16 method.invoke(target, getResourceToInject(target, requestingBeanName)); 17 } 18 catch (InvocationTargetException ex) { 19 throw ex.getTargetException(); 20 } 21}

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

getResourceToInject(target, requestingBeanName)

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

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

1if (factory instanceof AutowireCapableBeanFactory) { 2 AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory; 3 DependencyDescriptor descriptor = element.getDependencyDescriptor(); 4 if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) { 5 autowiredBeanNames = new LinkedHashSet<>(); 6 resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null); 7 if (resource == null) { 8 throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object"); 9 } 10 } 11 else { 12 resource = beanFactory.resolveBeanByName(name, descriptor); 13 autowiredBeanNames = Collections.singleton(name); 14 } 15} 16else { 17 resource = factory.getBean(name, element.lookupType); 18 autowiredBeanNames = Collections.singleton(name); 19}

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

getBean(name, element.lookupType)

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

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

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

1Object wrappedBean = bean; 2if (mbd == null || !mbd.isSynthetic()) { 3 //对bean的前置处理,其中@PostConstruct就在此步骤中 4 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 5} 6 7try { 8 //调用初始化方法如果bean实现了InitializingBean接口,则先执行InitializingBean接口的afterPropertiesSet方法,然后执行xml或注解设置的init-method方法。 9 invokeInitMethods(beanName, wrappedBean, mbd); 10} 11catch (Throwable ex) { 12 throw new BeanCreationException( 13 (mbd != null ? mbd.getResourceDescription() : null), 14 beanName, "Invocation of init method failed", ex); 15} 16if (mbd == null || !mbd.isSynthetic()) { 17 //对bean进行后置处理,对象的代理发生在此步骤中 18 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 19}

在初始化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。

点赞
收藏

评论区

加载中...

相关推荐

Android AOSP基础(二)AOSP源码和内核源码下载

title:"AndroidAOSP基础(二)AOSP源码和内核源码下载"date:20193900:18cover:https://s2.ax1x.com/2019/05/27/VZRBi4.jpgtag:AOSP基础categories:Android框架层本文首发于微信公众号「后厂技术官」前言这篇文章我们来学习如何下载AOSP源码,

spring源码

SpringIOC容器源码解析系列,建议大家按顺序阅读,欢迎讨论(_spring源码均为4.1.6.RELEASE版本_)1.Spring源码IOC容器(一)构建简单IOC容器(https://my.oschina.net/u/2377110/blog/902073)2.Spring源码IOC容器(二)Bean的定位解析注

spring源码解析

前言上篇我们介绍了spring容器加载的方式,并重点介绍了基于xml配置解析和注解扫描两种容器加载的方式,封装和注册beandefinition的过程。今天我们分享BeanDefinition注册后的另一个重要过程bean的实例化过程的源码。容器加载流程!spring源码解析spring容器加载源码(bean实

0源码基础学习Spring源码系列(二)——Spring如何解决循环依赖

本篇文章适用于0基础学习spring源码,文章重点解析spring如何解决循环依赖,并从解决循环依赖过程、三级缓存在循环依赖中的作用、解决代理对象的问题、二级缓存、初始化几个维度出发,解析spring源码。

Spring 源码阅读神器

Spring是java最优秀的框架之一,其源码属于Java开发者拜读圣经。Spring源码阅读障碍Spring源码非常的优秀,但其设计,代码量非常庞大,对于开发者自身,有些无从入手的感觉。没有体系的阅读很难学习到Spring的精髓,同时因其复杂让很多开发者望而却步。!(https://os

19_BasicTaskScheduler0 基本任务调度类基类(一)——Live555源码阅读(一

19\_BasicTaskScheduler0基本任务调度类基类(一)——Live555源码阅读(一)任务调度相关类这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。本文由乌