首页IT科技spring bean注入过程(0源码基础学习Spring源码系列(一)——Bean注入流程)

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

时间2025-06-20 08:21:30分类IT科技浏览7365
导读:作者:京东科技 韩国凯...

作者:京东科技 韩国凯

通过本文               ,读者可以0源码基础的初步学习spring源码                     ,并能够举一反三从此进入源码世界的大米!

由于是第一次阅读源码       ,文章之中难免存在一些问题               ,还望包涵指正!

一               、 @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       。

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

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

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

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

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

@Autowired SessionUtil sessionUtil;

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

当注册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

当只有一个bean时                     ,可以直接注册 @Autowired SessionUtil sessionUtil; 当有多个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的注册流程主要包含两个部分:

容器的启动阶段及预热工作 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 were already creating this bean instance: // Were 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主要有以下几步:

解析bean的class文件                     ,为后面的根据class文件通过反射创建对象做准备       。 预处理bean的Override属性,预处理的方式也比较简单               ,就是在方法prepareMethodOverride中判断一下                     ,如果lookup-method标签或者replaced-method标签中配置了bean中需要覆盖的方法       ,就将MethodOverride中的overload属性值设置为false              。 尝试通过反射获取被代理的bean                      。 真正创建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主要有以下几个流程:

首先通过class根据反射创建对象,此时该对象的所有的属性都为空                      ,可以理解为我们new出的空属性对象                      。 解析@Autowired @Value @Resource @PostConstruct这些注解                     ,但并没有发生属性注入的行为              。 是否需要提前曝光,用来解决循环依赖时使用               ,主要作用是如果需要代理会返回代理对象                     ,如果不需要代理       ,返回前面创建的对象 将第一步实例化完成的空属性对象填充属性               ,其中如果该bean依赖了其他bean                     ,也会在此步骤将依赖的bean装配       ,如果bean已经被创建        ,则直接属性注入                     ,如果不存在              ,则创建bean        ,创建方式跟本bean相同                      ,可以理解为递归       。 将实例化完成的bean对象初始化              ,主要查看bean是否实现了一些前置或后置或初始化的方法,如果是的话就执行                      。 循环依赖检查              。 根据scope注册bean。

可以看到                      ,经过以上的几个步骤                     ,我们就获取到了一个实例bean                      。

其中最重要的三个方法:

实例化bean 装配属性 初始化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 isnt 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); } 首先解析class文件与确认public权限                      。 如果存在 Supplier 回调                      ,则调用 obtainFromSupplier() 进行初始化              ,因为反射获取对象的效率比较低       。 如果args为空且使用那个构造函数已经被确定了,则进行标记                      ,后续直接选择使用那种构造方法              。 如果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步

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

我们查看代码发现                      ,无论第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主要有两个实现类:

AutowiredAnnotationBeanPostProcessor 处理@Autowired和@Value注解bean定义信息 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)有几个实现方法              ,比较重要的是:

AutowiredAnnotationBeanPostProcessor        ,主要装配属性是@Autowired与@Value的属性 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两个方法的大概逻辑就是获取获取所有实现其接口的类                     ,然后执行其中被覆盖的方法              。

常用的注解执行顺序如下:

@PostConstruct注解修饰的方法 InitializingBean接口的afterPropertiesSet()方法 init-method指定的方法 @PreDestroy注解修饰的方法 DisposableBean接口的destroy()方法 destory-method指定的方法

并且在代码中可以看到,前置处理与后置处理都可以改变bean。

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

BeanFactoryPostProcessor存在于容器启动阶段       ,而BeanPostProcessor存在于对象实例化阶段               ,BeanFactoryPostProcessor关注对象被创建之前那些配置的修改                     ,而BeanPostProcessor阶段关注对象已经被创建之后的功能增强       ,替换等操作        ,这样就很容易区分了                      。

BeanPostProcessor与BeanFactoryPostProcessor都是Spring在Bean生产过程中强有力的扩展点                      。Spring中著名的AOP(面向切面编程)                     ,其实就是依赖BeanPostProcessor对Bean对象功能增强的。

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

2.4 总结

用简单的话描述一下                      ,创建一个bean的过程大概包括三部分:

通过反射实例化bean 属性装配以及填充 初始化              ,包括init-method       、以及其前后三个步骤                      。其中AOP增强就是发生在初始化之后的applyBeanPostProcessorsAfterInitialization的步骤中       。

通过以上的步骤,就可以获得我们可以正常使用的一个bean              。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
朋友圈转发广告需要承担法律责任吗(发广告赚钱有哪些-朋友圈转发广告就能赚钱?馅饼还是陷阱?)