接着往下看,我把代码重写贴出来, 下面还有五件大事,这四件大事说完了,本文就结束了
第一: 是applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
回调后置处理器,进行有关注解的缓存操作
第二: 是getEarlyBeanReference(beanName, mbd, bean)
获取一个提早暴露的beanDefinition对象,用于解决循环依赖问题
第三: 将刚才创建原生java对象存放一个叫singletonFactories
的map中,这也是为了解决循环依赖而设计的数据结构,举个例子: 现在准备创建A实例, 然后将A实例添加到这个singletonFactories
中, 继续运行发现A实例依赖B实例,于是在创建B实例,接着又发现B实例依赖A实例,于是从singletonFactories
取出A实例完成装配,再将B返回给A,完成A的装配
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"); } // todo 重点再来看这个 addSingleFactory // todo 将原始对象new出来之后放到了 这个方法中的map中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; // todo 到目前为止还是原生对象 try { //todo 用来填充属性 //设置属性,非常重要 populateBean(beanName, mbd, instanceWrapper); // todo 经过AOP处理,原生对象转换成了代理对象,跟进去 //执行后置处理器,aop就是在这里完成的处理 exposedObject = initializeBean(beanName, exposedObject, mbd); }
接着看populateBean(beanName, mbd, instanceWrapper);
方法,这个方法很重要,就是在这个方法中进行bean属性的装配工作,啥意思呢? 比如现在装配A实例,结果发现A实例中存在一个属性是B实例,这是就得完成自动装配的工作,源码如下:
如果仔细看,就会发现两个事:
第一: 如果不出意外,就会出现两次后置处理器的回调,第一后置处理器的回调是判断当前的bean中是否存在需要装配的属性,而第二波后置处理器的回调就是实打实的去完成装配的动作
第二: 下面的第一个处理器其实就是spring启动过程中第一个回调的处理器,只不过调用了这个处理器的不同的方法postProcessAfterInstantiation()
,默认返回ture表示按照正常的流程装配对象的属性,返回false,表示不会继续装配对象中的任何属性
而我们则继续关注下面方法中的第二个后置处理器的,看看Spring是如何完成属性的自动装配的,关于这部分的跟踪,我写在下面代码的后面
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { //todo 进行了强转, InstantiationAwareBeanPostProcessor这个接口前面说过 // todo 只要是通过这个接口返回出来的bean Spring不在管这个bean,不给他装配任何属性 //todo 当前这里没有用它这个变态的特性 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // todo postProcessAfterInstantiation()默认是返回true, 加上! 表示false if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } // todo Spring内部可以对BeanDefinition进行设置值, 参照自定义的 BeanFactory中获取到BeanDefinition.getPropertyValue().addXXX(); PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // todo 判断当前bean的解析模型是 byName 还是 byType // todo 再次验证了::: 当程序员直接使用@Autowired注解时, 既不是ByName 也不是ByType, 而是No if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { if (pvs == null) { pvs = mbd.getPropertyValues(); } //todo 获取出对象的所有set get方法,现在是有一个 getClass()方法,因为继承了Object, 没什么其他卵用 PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
好,继续跟进pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(),
,看看spring如何完成属性的自动装配,当然,还是那句话,如果我们直接跟进去这个方法进入的是InstantiationAwareBeanPostProcessor
抽象接口抽象方法,而我们关注的是它的实现类
AutowiredAnnotationBeanDefinitionPostProcessor
的实现,打上断点依次跟进
@Override public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { // todo 跟进来, 目的是 为 beanName 填充上属性 bean metadata.inject(bean, beanName, pvs);
跟进
metadata.inject(bean, beanName, pvs);
源码如下:
可以这样理解,在下面的方法中遍历当前对象中所有可能需要依赖注入的属性字段
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // todo 这里的 InjectedElement 表示单个的需要注入的元素对象 Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isDebugEnabled()) { logger.debug("Processing injected element of bean '" + beanName + "': " + element); } //todo 跟进 AutowiredAnnotationBeanPostProcessor 对这个方法的实现, 在600多行处 element.inject(target, beanName, pvs); } } }
跟进这个inject()
我是手动删除了这个方法中其他的很多判断,仅仅保存下来了下面我们关注的逻辑,逻辑很清楚,上面的代码中不是在遍历所有需要自动装配的field吗?如果找到了的话,就得完成自动装配,自动装配什么呢? 其实就是自动装配上当前对象依赖的其他的对象而已,因为我们使用的后置处理器是AutowireAnnotationBeanPostProcessor
通过下面的代码就能得出结论就是@Autowired
默认情况下是通过反射实现的自动装配
// todo 来到这里 @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } }
我们一路往下跟进resolveDependency()
我们关注这个方法如下代码:
if (instanceCandidate instanceof Class) {// todo !!!!!当运行到这行代码时, myService还没有被实例化(singletonObjects中没有) 执行完这一个行代码之后, IndexDao1完成了对myService的装配 instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); }
跟进这个resolveCandidate()
源码如下:
很直接发现,出现的递归的现象,这其实解析清楚了Spring是如何完成属性注入的,就是只不过前前后后很多接口很多类,会扰乱这个阅读的过程
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) throws BeansException { // todo 从bean工厂的获取, beanName = myService requiredType = com.changwu...OrderService2 , 跟进去这个方法, 他调用了AbstractBeanFactory中的getBean(){ doGetBean();} return beanFactory.getBean(beanName); }
完成装配后,其实现在的对象依然是原生的java对象 回到AbstractAutowireCapableBeanFactory
中的initializeBean()
方法,源码如下, 看了下面的代码就是知道了为什么applyBeanPostProcessorsBeforeInitialization
和init()
和applyBeanPostProcessorsAfterInitialization()
之间的调用顺序了
还有最后一个秘密需要揭开: Spring的AOP不是产生了代理对象? 那什么时候完成的代理呢?毕竟从我开始写这篇文章到最后都没有看到,其实AOP的实现就在下面的代码中
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //todo 执行全部的后置处理器的 Before方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // todo 执行所有的init方法 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()) { // todo 执行所有的后置处理器的 after方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
我们在前面知道当遇到这个AbstractAutoProxyCreator
时,回调它的before()
方法时,仅仅是标记哪些对象需要进行增强哪些对象不需增强,而没有立即生成代理对象
现在我们关注这行代码wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
,生成代理对象的逻辑就在这里面
@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { // todo 进入 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
看这个方法wrapIfNecessary(bean, beanName, cacheKey);
最终会进入这个实现中
大家可以看到Spring为bean生成了代理对象,默认会先检查被代理的对象有没有实现接口,如果实现了接口,就是用jdk动态代理,否则就看看有没有cglib的相关依赖,如果存在的相关依赖而没有实现接口,就会使用cglib的代理模式
另外,补充通过编码的方式控制 下面的if条件
config.isOptimize()
-> 可以通过XMl配置, 默认falseconfig.isProxyTargetClass()
->@EnableAspectjAutoPeoxy(true)
默认也是false
@SuppressWarnings("serial") public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { //todo 目标对象是一个接口, 同样是使用jdk的动态代理 return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { // todo 所以默认使用的是 jdk的动态代理 return new JdkDynamicAopProxy(config); } }