图1
图3
图4
图5
图6
图7
添加了BeanPostProcessor()
图8
图9
判断是否代理过,如果实现了EnHancedConfiguration这个接口证明被代理过,直接返回。
图10
图11
图12
图13
代理后的对象有$beanFactory对象的属性。
图14
图15
得到beanFactory工厂。现在的问题是要理解原始类和我们的cgilb产生的类有什么关系呢,图16为原始类。问题来了,那我调用Appconfig appconfig = getBean(); 获取的appconfig应该是图17xxxx,调用的方法应该是xxxx.userService(); 这个方法里面的行为是否发生了改变呢或者是有什么关联呢,这个是要研究的问题。
beanMethod是调用的方法。判断执行的方法和调用的方法是不是同一个方法,如果是则证明是第一次调用采用new的方式,如果不是采用去factory中getBean()中获取。那到底什么是执行方法,什么是调用方法呢。图22有解析。如果是的话是new吗,看spring 的源码不是new 而是直接调用父类的方法。invokeSuper()方法。如果不是则只需resolveBeanReference()方法。来 $$ beanFactory.getBean()图23.
图16
15行应该去掉static。
图17
假设cglib生产的类是这样的。
图18
为获取真正的cglib代理类。
图19
this.CGLIB$CALLBACK_0对应的是图20 LubanMethodInterceptor类。如果var10000不等于null 调用LubanMethodInterceptor 的intercept方法。
图20 LubanMethodInterceptor
method为当期调用的方法也就是执行方法,methodProxy为代理方法也就是调用方法。举例说明,当第一次调用时,当期的method 的为 query()方法,methodProxy为query()方法。当第二次调用的时候method为query()方法,methodProxy为query2()方法。图22。
图21
currentlyInvoked获取的时调用方法,method为执行方法。比较两个方法的方法名称是否相当,参数列表是否相等,如果相等证明是第一次采用new的方式,如果不相等证明不是第一次采用获取的方式。
图22
query()方法没有嵌套方法时 即为调用方法又为执行方法。 query2()方法有嵌套方法这个时候,query2为调用方法,query()为执行方法。
图23
最重要的是beanFactory.getBean()整个方法,获取bean返回。
这个beanFactroy.registerDependentBean()方法设置了bd.
其他的都不重要。
图24
图25
延迟加载,就是在@configuration注解处理完之后才处理这个类。
图26
图27
总结:
1.BeanPostProcessor spring的后置处理器,作用是插手bean的实例化过程,实例化之后,在bean没有放在容器singLetonObjects<k,v>之前。图28 ,经典场景@PolstConstruct,aop
BeanPostProcessor 是 bean 后置处理器,是spring提供的一个扩展点,我们程序员只需要去实现BeanPostProcessor的一个接口,就能插手bean的一个实例化过程。咋么插手呢,就是在bean放在singLetonObjects之前 做一个插手。对bean进行一些改变。
经典场景,bean的生命周期回调 ,那是哪个类实现这个BeanPostProcessor类,完成回调呢,是这个图29 是这个类CommonAnnotationBeanPostProcessor
2.BeanFactroyPostProcessor 图30 spring 的核心类ConfigrationClssPostProcessor ,的postProcessBeanFactory() 这个方法 ,来判断是否加了@Configration注解如果加说明是一个全注解(full).如果是全注解这个方法会使用cglib生成代理类,如果没有加还是原来的类。
3BeanDefinitionRegistryPostProcessor 图31 spring 的核心类ConfigrationClssPostProcessor 的postProcessBeanDefinitionRegistry() 这个方法来完成扫描,三种import的扫描,bean的扫描,判断类的注解是不是一个全注解。 先遍历BeanDefinitionRegistryPostProcessor(spirng内部的,和自定义的) ,那么怎么操作算是自定义的,手动添加一个add BeanPostProcessor();图32
4.importSelector 图27 通过这个selectImports ()的方法返回一个全类名的字符串数组,把他变成bd,动态添加bd,注意这个bd是死的,为什么说这个bd是死的呢,因为从class到bd这个过程是spring来操作,我们程序员没有办法干预。class是什么spring就会操作成什么样的bd放在容器中。 就相当于说spring告诉我们,你返回一个全类名我来帮你转化成bd.。当我们不需要动态的改变bd的时候我们选择用importSelector。如果我们需要动态的改变bd我们就需要用importBeanDefinitionRegistrar了。
5.importBeanDefinitionRegistrar 图26 比ImportSelector的类多了BeanDefinitionRegistry ,所以可以动态的改变bd. 通过registry来注册扫描器,然后通过扫描器把改变的bd添加到beanDefinitionMap中。还可以通过图37改变UserMapper的类型。
图28
图29
图30
图31
图32
图33
图34
图35
图36-0
图36
图37