范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

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

  作者:京东科技 韩国凯
  通过本文,读者可以0源码基础的初步学习spring源码,并能够举一反三从此进入源码世界的大米!本文第一部分将介绍@Autowired与@Resource的区别,第二部分则重点介绍SpringIOC的Bean注入流程。
  由于是第一次阅读源码,文章之中难免存在一些问题,还望包涵指正!一、 @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的信息。                
  以上就是一个由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连接的时候可以这样配置:                                                                        
  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{      @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 doGetBean(       String name, @Nullable Class 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) 创建beanprotected 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 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装配属性初始化bean2.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); } 首先解析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。

当我们真的喜欢上一个人的时候,为啥总是想亲对方?当我们喜欢上一个人的时候,为什么总是想亲对方?人从小到大就有很多冲动,小的时候喜欢整天待在妈妈身边,长大之后,我们发现外面的世界实在是太精彩了,有好吃的零食,喜欢的玩具,还有长相好刘德华我爱她比爱老婆多!年关将至,又快到了我们的好朋友刘德华准时携金曲恭喜发财在各大超市上线的欢快时节啦。提到刘德华,前段时间,有网友晒出了他和妻子一起在女儿学校参加活动的照片,称这个星爸非常称职。照片中迷茫什么?选择自己喜欢的方式,过完这一生,不就好了让世界听见你的声音你现在应该做的是早点离开家乡,脱离原生家庭,离开那个亲戚圈,熟人圈,大宗族圈,远离那个只知道喝酒吹牛的圈子。早点找到自己的爱好,锻炼自己的本事,完善自己的人格,在比起被别人左右情绪,更喜欢现在的自己人到中年,终于到了无人问津的年纪,没有社交,没有攀比,没有暧昧。不想合群,不想内卷。比起被别人左右情绪,更喜欢现在的自己!突然发现没有灵魂伴侣,没有特别爱的人,是那么孤独,整个世界喜欢到爆炸的绝赞文案头条创作挑战赛1。在这个人人都具备手机的条件下保持联络竟然成了最难的事情。2。周围都是花,怎么会执着于一朵。3。旋转的地球上肯转身,总有新故事值得盼望。4。耳机里的歌声,是与世隔绝娃要生书也要读!老公一句话,我从宝妈成研究生,他从老板成奶爸这是我们讲述的第1251位真人故事我是罗小肥,一个90后广东人,如今在香港生活。俗话说男怕入错行,女怕嫁错郎。我的一切好运,都是从嫁给老朱开始的。曾经我是一个处处不得志的灰姑娘,考谢谢你医生甜宠番外白医生送老婆爆款泳装,又吃醋反悔影视图文连载计划接着前面的甜宠风格这天下班,肖砚坐在电视前追剧。白医生到家时,手里拿了两个一模一样的盒子,有点儿神秘兮兮地走过来,坐到她身边。老婆,送你的礼物。哦?肖砚一边拿到手中天助畅运IPO募资5。79亿元,花10万买下研报遭监管问询中新经纬12月16日电(邓芷若马静)近日,北京天助畅运医疗技术股份有限公司(下称天助畅运)更新IPO问询回复。天助畅运此次IPO募资总额为5。79亿元,其中5。18亿元用于天助畅运从理论到实践,一级市场到底怎么搞ESG?文张一统筹黄祝熹出品36氪创投研究院今年9月,一则来自巴塔哥尼亚(Patagonia)的公告,在朋友圈疯狂转发。这家被视为户外Gucci的美国运动品牌创始人YvonChouinar科学家教惩戒不等于体罚科学家教育儿育己惩戒是教育的一部分,当孩子犯了错误,适当的惩戒必不可少。但是惩戒不等于体罚,一旦失控,就是违法。惩戒不等于体罚1hr课间去走廊护导,一群小不点儿立马围上来,跟我各种6岁前的数学启蒙很关键,但偏偏不少老母亲却用错力了1hr之前答应学前家长朋友们要写的启蒙系列,我已经陆续写完了学前习惯语文英语启蒙篇小升初回头看6岁前最该鸡点啥?性价比才是最高的!海淀妈妈掏心回头看6岁前大语文启蒙规划实操一文说透
罗曼蒂克RomantikM309S(卡带播放器)80年代便携式收音机产品简介制造厂商罗曼蒂克Romantik产品型号M309S产品类型无线电收音机卡带播放器生产日期1989年制造国家德国音响颜色黑色功耗14瓦尺寸480260100毫米(宽x高x深)猫头鹰将推出NHAM5,新款NHD15或如期而至近日,奥地利散热器厂商猫头鹰(Noctua)发布了新的产品路线图。按照今年春季时候公布的计划,2023年第一季度会推出白色版散热风扇,不过已延后到了2023年第三季度。幸运的是,已400以内蓝牙耳机哪款好?南卡和FIIL蓝牙耳机测评大PK最近南卡新发布的南卡小音舱真无线耳机有不少学生党小伙伴们都有热切关注,还有有一部分小伙伴比较疑惑南卡小音舱真无线耳机和FIILCCnano蓝牙耳机这两款蓝牙耳机哪个更好,所以今天准耳机该选什么样?韶音不入耳耳机带来骨传导黑科技欢迎来到awesome科技的频道,聊聊耳机该选什么样?韶音不入耳耳机带来骨传导黑科技。今天为大家点一首比较好听的歌孤勇者随着蓝牙耳机的越来越流行,耳机似乎和手机一样成为出门必备的随网易新款词典笔中英文学习听写难题也解决了全新升级还记得小时候学习必备的两本工具书就是新华字典和牛津高阶英汉双解词典,大一些了就有好记星文曲星等电子词典,帮助提高英语成绩确实很有效果。而现在电子学习工具最方便好用的无疑是电10月13日战神手机蓄势待发,荣耀X40GT发布会定档昨天,荣耀表示荣耀X40家族将迎来新成员荣耀X40GT。今天荣耀再次公布新品消息,实力霸屏满帧战神荣耀X40将于10月13日发布,同时新品首个定妆照公布,新品预约同步开启,。荣耀X峰米S5激光投影仪值不值得买?峰米S5激光投影仪近期被各种草及社区平台吹得神乎其神,怀着好奇的心我一定要下单来看看这款投影仪,于是9月14日下单了,无语的是被告知无货需要等到9月底,于是我在10月8日小长假之后SWITCH四年老玩家分享从购买到使用的注意事项从新手一路走过来,也看过许多游戏大UP分享的心得,有些观点并不认同,这里分享一些我自己四年的使用体验,欢迎大家讨论SWITCH三种机型的选择首先是目前主流的三种机型LITE,续航版丰满女生怎么穿搭?不如看看程潇吧!正反面教学皆有大胸的姐妹们在夏天穿衣服是比较困扰的,怎么穿才能清纯一些?感觉大胸怎么穿都很sexy,而且也很显壮,夏天真的是让人又爱又恨。小格发现程潇就是一本行走的大胸穿搭教学,还是正反面的例子可疑的埃及法老们的胡须每看埃及拉美西斯一众法老们的胡须,便觉别扭滑稽,有画蛇添足的反感。胡子主要是三部分,嘴唇上的髭,两腮上的髯,下巴上的须(鬚)。法老们把髭和髯剔个净光,唯独留下须,还弄成长方形的柱体别买激光电视,大屏液晶电视真滴香平时最大的爱好就是看电影,买了新房,家里想买个大屏电视,预计是留了85吋100吋电视的位置投影仪我是不会考虑的,感觉和家里整体装修风格不搭,投影仪的幕布显得比较low,而且画质质量