Spring 源码(四,五)

 

图1

 调用refresh() 方法,来解析注解。

图2

 执行已经注册的后置处理器.

图3

726行gentBeanFactoryPostProcessors() 方法,返回的List 是  是程序员 通过调用AnnotationConfigAppLicationContext.addBeanFactoryPostprocessor() 方法手动添加的。如果没有添加这个list就是空。调用invokeBeanFactoryPostProcessors()方法,图7

图4

图5

图6

图7

根据图3知道gentBeanFactoryPostProcessors() 方法为空,因为没有手动调用AnnotationConfigAppLicationContext.addBeanFactoryPostprocessor() 所以benFactoryPostProcessors为空。 定义了存放BeanFactoryPostProcessor 的list  regularPostProcessors,和存放BeanDefinitionRegistryPostProcessor 的list  registryProcessorsList 因为gentBeanFactoryPostProcessors() 获取的list为空,所以这两个list都为空。

遍历postProcessorNames ,把每一个ppName放在prrocessedBFeans中。

 

这个不重要,是排序的。和上面差不多。为什么要写两遍啊。因为通过判断 if(!processedBeans.contains(ppName))  ,有可能这个是在之后新添加的ppName,所以processedBeans中没有的。

为什么这里在处理BeanFactoryPostProcessors的i时候的还要在处理一次BeanDefinitionRegistryPostProcessor。因为如果有一些类继承了BeanDefinitionReistryPostProcessor类,所以要再执行一下他的父类。 例如ConfigurationClassPostProcesstor的类就是继承了BeanDefinitionRegistryProcessor类。  registryProcessors中包含的是BeanDefinitionRegistryProcessor 。regularPostProcessors的list中包含了BeanFactoryPostProcessors的类。

图8

图9

ConfigurationClassPostProcessor 类继承BeanDefinitionRegistryPostPrpcessor 类。 所以 调用的ConfigurationClassPostProcessor 类的postProcessBeanDefinitionRegistry()方法。

图10

图11

图12

获取那beanDefinitionMap中6个对象的bean中的名字, 遍历,获取他们的bd, 判断bd 的confinurationClass属性是full或者lite 则认为已经处理过。

检查注解是不是@Configuartion  或者 @Component @ComponentScan,@Import @ImportResource 把db添加到configCandidates的list中。

排序不重要.

bd的名称生成器,如果有就利用,没有就用spring默认.

把 加了configCandidates的list去重得到 cadidataes来保证 Appconfig类只处理一次。

图13-0

 

图13

图14

图15

就是判断当前这个注解类有没有被其他类Imported.如果是证明就已经存在了。

把configClass转换成sourceClass。调用doProcessConfigurationClass()。 .

图16

处理内部类 就是在AppConfig类里的内部类.不重要,一般没有用到,propertySources下次课讲。

处理componentScan注解。为什么要循环,因为componentScan注解是一个数组。图21.

parse()方法。图17componentScan ='com.luban'

处理Import 有3中情况,第一中是ImportSelector,第二种是ImportBeanDefinitionRegistrar ,第三种情况是普通类。图36 应用实例1,图37应用实例2 图38 源码分析。

图17

new ClassPathBeanDefinitionScanner ()  这个是真正解析@componscan注解的scan对象。而不AnnotationConfigApplicationContext的scanner对象图27 。那什么时候用呢,图28会用到AnnotationConfigApplicationContext的scanner对象.80行得到名字生成器,生成名字放到beanDefinitionMap中的的名字。85行讲到web的时候才讲。

遍历当中的过滤 。根据includeFilter 和excludeFilter 不同设置不同的scanner中。在扫描中过滤。是否懒加载默认不是懒加载。拿到所有包的名字

调用核心代码doScan()代码

图18

循环包,调用findCandidateComponents(basePackage) 利用asm技术读取class文件。 findCandidateComponents 调用scanCandidateComponents 返回的是ScannedGenericBeanDefinition   ( ScannedGenericBeanDefinition    extends  GenericBeanDefinition  extends AbstractBeanDefinition) ,所以为这个bd设置默认值。

如果加了注解的就处理这个注解。图34

加入到beanDefinitionMap中。图35

图19

图20

利用asm技术来读取文件 并转换成resources文件。

ScannedGenericBeanDefinition  的继承关系图29 ScannedGenericBeanDefinition extends  GenericBeanDefinition  extends AbstractBeanDefinition

图20-0

图21

图22

是不是接口,是不是能被创建,如果是接口永远不可能被放到beanDefinitMap中。

图23 

图28

图29

图30

图31

spring 为bd设置默认值。lazy默认读取的是appconfig 的值 ,autowireMode 默认是autowire_no  no的时候首先会bytype,然后再回byname

图32

图33

图34

判断每一个bd,判断如果bd 所对应的类中加了@Lazy的注解,取出注解的值 覆盖之前的默认值,如果没有就用之前的默认值。

图35

图36  

ImportSelector 实例1.

图37

 

 

ImportSelector 实例2 。动态的实现(如果加了@EanbleLuabn注解会有动态代理,如果没有加不会有动态代理 )动态代理。

图38

 

 

 首先判断这个类(MyImportSeletector)是不是实现了ImportSelector接口,得到他的Calss对象,635行调用它selectImports方法。得到类的全类名。依次把数组的类名转换为SourceClass类,然后,放在List中返回,递归调processImports()方法处理。

processImports()第一次调用的的时候,第三参数importCandidates获取的是 @Impolrt(MyImportSeletector.class) 的value值也就是参数为MyImprotSelectector类,这个类的接口 是Selector,所以 走的是 if(candidate.isAssignable(ImportSelector.class)){} 这个分支。第二次不用获取,直接把IndexDao3的全类名传进去,他既不是实现selector接口 也不是实现ImportBeanDefinitionRegistrar的接口所以走的else()分支。图15调用 processConfigurationClass() 。把indexDao3的全类名存在configurationClasses的map中。.

图39

 

图40

图41

图42

把这个类名数组遍历并转换为soruceClsass类型添加到annotatedClasses的List中。

图43

图44

图45

图46

图47

图48

图49

图50

图51 

configurationClassPostProcessors类中postProcessBeanFactory()方法。

图51-0

如果加了@Configuration 会使用cglib动态代理 打断点是xxx.proxy对象,如果不加不会使用 打断点是Appconfig对象。如果加了Configuration indexDao1就会被调用一遍 dao1-init 会打印一遍,如果没有加会调用两遍 dao1-init 会打印两遍。

图52

判断是不是一个全注解的类 full 也就加了@Configuration 就会放在configBeanDefs的map中。

图53

图54

当前类做为父类。enHancer.SetSuperclass(configSuperClass); 那为什么又要增强一个EnhancedConfiguration这样的接口呢,因为这个接口继承了BeanFactoryAware 。BeanFactryAware又继承了Aware ,并实现了SetBeanFactory()方法。那我们产生的代理对象就能够得到BeanFactory对象。那问题来了,为什么要得到这个BeanFactroy对象。图59有详细说明。

enhancer.setStrategy()是cglib生成类的一个策略。图60 。添加一个方法的过滤器,callbackFilter()。 参考例子图63.问题来了为什么不用jdk动态代理呢,因为jdk是基于接口的,appconfig不一定是实现接口的。

图55

图56

图57-0

图57-1

判断返回的是不是一个factoryBean ,对返回的对象再次进行代理,enhanceFactoryBean() 图图57-3。 为什么要进行两次代理呢,图 57

 

图57-2

图57-3

图57-4

图57-5

  第一次代理为 getObject() 方法,第二次代理为new IndexDao2代理。

图57-6

图57-8

自动注入一个beanFactory 。类似调用setBeanFactory()方法。

图58

图59

为什么要得到这个BeanFactroy对象。目标对对象 可以不可以拿到原始对象,可以如例子说,new IndexDao1() ,每调一次就会new一次,无法满足spring的单例要求。 那怎么生成单例的呢,只会产生一个对象呢,给目标对象做一个代理生成代理类,然后在代理类中改变他的行为,例如可以先从容器中获取,如果没有就new 一个,如果有return。 代理类直接可以通过factory.getBean()方法来获取可以用的类。

图60

spring扩展实现,继承了DefaultGeneratorStrategy .  declare_field声明一个属性。 为什么要声明一个属性呢,

图61

默认生成策略是DefaultGeneratorStrategy类 ,有生成字节码的,有生成类的。

图62

因为 生成的代理类 appconfigProxy 一定是继承Appconfig 实现 BeanFactory方法的。   肯定有个属性为BeanFactory 。spring 为这个代理类生成的属性。

 

图62-0

图63

o 为目标对象,method 为目标方法,methodProxy为代理方法。

利用cglib成功拦截目标对象。

 

cglib是操作字节码基于父类来的。是继承。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值