深入理解 Spring finishBeanFactoryInitialization (5)

我把源码贴在了下面,下面方法的目的就是选出一个策略来实例化一个对象, 那有什么策略呢? 这就看程序员是怎么配置的了, 程序员可以配置工厂方法,指定构造方法,或者是程序员没有做出任何干涉,让Spring按自己的方式去实例化

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. Class<?> beanClass = resolveBeanClass(mbd, beanName); /** * todo 检测一个类的访问权限, Spring默认是 允许访问非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()); } /** * 创建一个bean的快捷方式 */ boolean resolved = false; boolean autowireNecessary = false; // todo 是否是必须自动装配 if (args == null) { synchronized (mbd.constructorArgumentLock) { // todo if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; //如果已经解析了构造方法的参数,则必须要通过一个带参构造方法来实例 autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) {// todo 如果是需要自动注入的,就使用构造方法自动注入 // 通过构造方法自动装配的方式构造 bean 对象 return autowireConstructor(beanName, mbd, null, null); } else { //通过默认的无参构造方法进行 //todo 通过默认的无参构造方法 return instantiateBean(beanName, mbd); } } Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // todo 使用特定的构造方法完成自动装配 return autowireConstructor(beanName, mbd, ctors, args); } // No special handling: simply use no-arg constructor. //todo 使用默认的无参构造方法进行初始化 return instantiateBean(beanName, mbd); }

我们主要关注上面代码的 determineConstructorsFromBeanPostProcessors(beanClass, beanName)这个方法的目的就是推测实例化需要的构造方法, 为什么需要先推测构造方法呢? 因为Spring实例化对象时,需要使用特定的构造方法才能反射出对象,这时如果程序员指定了带参数的构造方法,spring就会使用这个构造方法实例化对象,如果程序员提供了一个不带任何参数的默认构造方法,Spring会忽略它,按自己的逻辑使用默认的无参构造

所以上面的if-else分支目的很明确,先是尝试获取全部的构造方法,然后看看有没有解析出来构造方法, 解析出来的话,就使用第一种逻辑,按照 特殊的构造方法模式进行处理,有解析出来,就使用默认的构造方法

我们进一步跟进这个determineConstructorsFromBeanPostProcessors(beanClass, beanName)方法,可以发现方法里面又是一波后置处理器的回调工作,这次选出的后置处理器的类型是SmartInstantiationAwareBeanPostProcessor,见名知意,这种处理器可以感知到心仪的构造方法,它的主要实现逻辑就是,查看这个将被实例化的对象中有没有添加了@Lookup注解的方法,有的话为这种方法生成代理,循环遍历所有的构造方法,看看这些构造方法上存在不存在@Value或者@Autowired注解,因为这些注解中存在required=true,只要存在这种注解,Spring就将他当成候选的构造方法,但是如果存在多个的话,Spring也不知道到底用哪一个,但是在这里Spring会将所有符合条件的都选出来,但是一般情况下,都可以正确的选出合适的构造

选择出合适构造方法之后,就根据不同的构造方法,选择使用不同的方式去实例化对象, 都有什么方式呢? 两种方式

方式1:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwpfgs.html