todo 总结这个类
在这个方法中,主要做了两件事:两件大事!!!
第一件大事:
在实例化Bean前,第一次调用后置处理器, 这件大事绝对是有历史意义的!!!为啥呢?大家想想,bean还没有创建呢!就已经可以插手bean的创建过程了,不是很刺激吗?接着看回调了什么后置处理器呢? Spring会循环所有的处理器检查当前被遍历的处理器是否是InstantiationAwareBeanPostProcessor
类型的,如果是的话呢,就执行这个后置处理器的postProcessBeforeInstantiation(beanClass, beanName);
方法
这个postProcessBeforeInstantiation()
是允许有返回值的,大家可以想想,这一点是不是有点可怕? 事实也是这样,后置处理器的目的是为了增强对象,而我们却可以在这里返回一个任何东西,狸猫换台子替换掉原始的,还没有被创建的对象,还有一点,就是一旦我们在这里真的是没有返回null,那后续Spring就没有义务在去为我们创建本来应该创建的对象了,代码通过if-else的选择分支会使得当前的对象不再经历其他后置处理器的增强,最终执行它父类的postProcessorAfterInitialization()
补充一点,我们通过@EnableAspectjAutoProxy添加到Spring上下文中的AnnotationAwareAspectjAutoProxyCreator
对象其实就是这个类型InstantiationAwareBeanPostProcessor
,也就是说在这里这个接口的相关方法会被回调,下面看看他的实现类AbstractAutoProxyCreator
对这个before()
方法的重写实现,源码如下:
主要逻辑就是找出需要产生代理增强的bean(切面类),和普通的bean, 需要增强的bean放在advisedBeans
里面,因为需要增强的bean是需要动态植入其他逻辑的,所以不放在一起
判断当前bean是否是基础类型的,比如: Advice PointCut Advisor AopInfrastructureBean 或者是 切面Aspectj 都算是基础类型,标注这些信息的类,是不会被增强的,标记false
注意啊,上面说的都是作用都是进行了一下标记
//todo 跟进来 @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } // todo 亮点就是在这里, 如果是我们切面类来到这里,条件是满足的 // todo advicedBeans 见名知意: 通知beans // todo Spring用它标识, 被放在这个方法中的类,全部都不会被增强 // todo 满足什么条件时,通过检查呢? 就是检查是否标记有 @Aspectj @Before ... 等注解 // todo 说的再直接一点, 就是返回了null, 表示当前的切面仍然需要按照正常的流程创建出来,但是这里进行标记了 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // Create proxy here if we have a custom TargetSource. todo 如果我们有一个自定义的TargetSource,在这里创建代理 // Suppresses unnecessary default instantiation of the target bean: // todo 抑制不必要的目标bean的默认实例化: // The TargetSource will handle target instances in a custom fashion. todo TargetSource将以自定义方式处理目标实例。 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
经过上面的标记,在哪里产生的代理对象呢?其实是在AbstractAutowireCapeableBeanFactory
中的initializeBean()
方法中实现的postProcessAfterInitialization()
实现的,在本文的末尾展开讨论
第二件大事: 实例化对象, 继续跟进
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("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. // todo 做各种各样的属性值的赋值, 比如这种 通过Spring的Bean传递给Spring框架的值 ==> bd.setPropertyValue("aaa") Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. // todo 处理 lookup-method 和 replace-method 配置,Spring 将这两个配置统称为 override method try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // todo 在实例化之前完成一次解析操作,这也是 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 { //todo 调用 doCreateBean 创建bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } }
我们继续跟进doCreateBean(beanName, mbdToUse, args);
方法, 同样是本类AbstarctAutowireCapableBeanFactory
的方法,源码如下: 这个方法也是无与伦比的重要,那这个方法中做了什么事情呢?如下
- 创建一个 BeanWrapper,用来存放bean+其他属性
- 创建bean的实例,封装进上面的BeanWrapper中
- 分两次调用处理处理器
- 设置属性,填充属性
- 经过AOP处理,将原生对象转换成Proxy
- 返回BeanWrapper
因为这个方法简直太重要了,上面列举的每一点都值得我们仔细分析,我们每一条的分析都写在下面代码的下面
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. // todo BeanWrapper 用来包装bean BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { // todo 一开始 factoryBeanInstanceCache 这个map中是没有值的, 所以进入下面的if instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } // todo !!!!!!!!这里获取出来的对象是原生对象!!!!!!!!!!!! final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; // todo 到目前为止还是原生对象 //todo 用来填充属性 //设置属性,非常重要 populateBean(beanName, mbd, instanceWrapper); // todo 经过AOP处理,原生对象转换成了代理对象,跟进去 //执行后置处理器,aop就是在这里完成的处理 exposedObject = initializeBean(beanName, exposedObject, mbd); return exposedObject; }
实例化对象
我把源码贴在了下面,下面方法的目的就是选出一个策略来实例化一个对象, 那有什么策略呢? 这就看程序员是怎么配置的了, 程序员可以配置工厂方法,指定构造方法,或者是程序员没有做出任何干涉,让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:
这是比较复杂的方式,此时Spring需要在这个方法内存比较好几个候选的构造方法,计算它们的差异值,最终值最小的构造函数就是将要用来实例化对象的构造函数,当然很可能是选不出合适的构造函数的,于是Spring没有立即抛出异常,而是将异常添加进bean工厂的suppressedExceptions这个set集合中
如果成功的选择出来一个构造函数,就会使用jdk原生的反射机制,实例化一个对象
autowireConstructor(beanName, mbd, ctors, args);
方式2:
直接使用JDK原生的反射机制,实例化一个对象
instantiateBean(beanName, mbd);
小结:
代码看到这里,方才说的有才华的那个类AbstactAutowiredCapatableBeanFactory
中的doCreateBean()
方法的instanceWrapper = createBeanInstance(beanName, mbd, args);
也就看完了, 到这里也就知道了,Spring会先把所有满足条件的bean全部实例化存放起来,这里的对象是百分百原生java对象,不掺水不含糖