spring源码 bean的生命周期

问:谈谈对spring的理解

答:总分思想,先说对spring的总体认知,再说小一点的比如:IOC,AOP,IOC如何实现,生命周期,循环依赖等

IOC:控制反转

xml和注解创建对象的流程

xm文件通过IO流读取到内存,再通过SAX和dom4j解析成一个document对象,里面有很多node节点,每个节点包含很多key和value值,将这些kv分别放到某个具体对象中去

注解,通过反射获得class对象,如果是@service等注解就直接创建bean

创建bean完整过程

通过xml或者注解获取到的bean的定义信息放进容器中的BeanDefinitionMap,

BeanDefinitionReader,用来读取xml和注解,对格式进行规范和约束,读取Bean定义信息后存进BeanDefinition。通过BeanFactoryPostProcessor来对BeanFactory进行修改(如进行占位符的替换,将配置文件中的具体值替换掉bean参数中的占位符),此时拥有了更加完整的BeanDefinition对象,可以进行创建bean,然后使用bean,销毁bean。

反射创建对象的步骤

PostProcessor 增强器

作用:提供额外的扩展功能,

常用的是BeanFactoryPostProcessor(针对Bean工厂)和BeanPostProcessor(针对Bean),用来解析BeanDefinition对象,使得变成一个完整的BD对象

BeanFactory

通过BeanFactory能对容器中的BeanDefinition进行修改

Spring工厂最底层的类就是这个BeanFactory接口,他定义了工厂的基本操作,也就是存取,也就是getBean这些操作都是这个接口而生

BeanDefinitionRegistryPostProcessor

注册bean

bean的生命周期

概念:从对象的创建到使用到销毁的过程

实例化和初始化的区别

bean对象分为自定义对象和容器对象(容器对象如BeanFactory,ApplicateContest等)两种,

实例化是在堆空间中申请空间,对象的属性值一般是默认值,用反射创建对象的过程(由createBeanInstance这个方法实现)

初始化:先对自定义属性赋值(populateBean方法内用set方法进行赋值),再对容器对象属性赋值(检测aware相关接口并设置依赖),这里aware的作用是提供一个统一判断的标记:即没实现aware接口的对象就是属性都是自己定义的,实现了aware接口的属性值是容器对象,需要调用容器的getset方法来设置属性(invokeAwareMethods里面做统一判断)。如果不设计这样一个aware接口,就需要在每个属性被赋值时都判断一下 当前属性是否是容器对象。

至此,对象的创建和属性赋值已完成,已经得到了一个普通对象,但是对象还不能使用,因为spring要考虑扩展性。

BeanPostProcessor接口包含2个方法

1.

前置处理方法

2.

后置处理方法

从方法名字可以看出,这里的前置和后置是针对initialization初始化方法来说的,这个初始化方法叫invokeInitMethods,他会判断bean是否实现了initalizingBean接口,实现了就会调用这个接口的afterPropertesSet方法进行一些初始化操作

BeanPostProcessor接口用途:AOP

AOP底层实现原理:动态代理(2种实现方式:jdk和cglib)

BeanPostProcessor接口的一个重要实现类:AbstractAutoProxyCreator,用来创建代理对象。

在这个实现类中,前置方法中直接return bean了,没做其他操作

但是在其后置方法中是有逻辑处理的

进入这个wrapIfNecessary方法,在方法尾部找到一句有关创建代理的代码:

进去这个createProxy方法,找到真正创建代理对象的代码:

getProxy方法:

再进入getProxy方法:发现是AopProxy接口的抽象方法,所以点击查看实现:

可以选择一种代理方式创建代理对象。

注意:AOP是IOC整体流程中的一个扩展点

此时,Bean对象已经创建好了,可以使用bean对象了

销毁bean对象

时机:关闭容器时才会销毁

学习源码的方法论

BeanFactory和FactoryBean的区别

BeanFactory:不指根接口,而是bean对象创建的整体流程,Bean的生命周期是一个完整的标准化的流程,相对比很麻烦

Factorybean :私人定制

静态代理和动态代理

代理的目的是在调用被代理对象的方法时,能在方法执行前后加上自定义操作

静态代理

分为抽象主题对象、真实主题对象、代理主题对象。

作用

在调用被代理对象的方法时,能在方法执行前后加上自定义操作

缺点

由于一个代理主题对象可能需要代理多个真实主题对象,所以要从真实主题对象中抽取出抽象接口,所以偶联程度太高,要在真实主题对象中加一个方法,就要在抽象主题对象中定义这个方法,并且代理主题对象都要实现这个方法。

当代理对象同时代理多个真实主题对象,由于多个真实主题对象中会有大量不同的方法,都必须在抽象接口声明,并且每个真实主题对象都要实现所有的方法,十分臃肿。

动态代理

造成静态代理代码臃肿的原因是:抽象主题对象调用真实主题对象中的方法时,利用的是多态性,在调用前,给代理对象传的是哪个子类,调用的方法就调用的是哪个子类中实现的。这样需要从所有被代理的类中抽象出一个公共接口,包含所有方法,即所有被代理类都要实现这个接口。

???为什么代理对象也要实现这个抽象接口?

动态代理通过Proxy.newProxyInstance 来创建代理对象

使用反射的方式来调用被代理类的方法,动态代理分3个角色: 抽象主题角色真实主题角色增强主题角色

其中的增强主题角色就是实现了使用反射来调用被代理角色的方法。

增强主题角色只需要实现InvocationHandler,使用其中的invoke方法调用被代理者的方法。只需要将被代理对象的方法和方法参数传递给invoke方法即可

类层次结构

UserService是公共接口

UserServiceImpl是被代理类

LogHandler是实现在代理对象的方法的前后添加自定义操作的类,实现了InvocationHandler接口。

  • 15
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值