1. List扩容主要实现步骤:
总的来说分两步,1.扩容:把原来的数组复制到另一个内存空间更大的数组中
2.添加元素: 把新元素添加到扩容以后的数组中
扩容的方法就是 add(E e)
看,其实add方法就两步,第一步:增加长度,第二步:添加元素到数组,第二步没什么说的,我们看看ensureCapacityInternal(int minCapacity)这个增加长度的方法
如果在添加的时候远数组是空的,就直接给一个10的长度,否则的话就加一
grow()方法是真正的增加长度,当需要的长度大于原来数组长度的时候就需要扩容了,相反的则不需要扩容。
这个地方注意这一句
int newCapacity = oldCapacity + (oldCapacity >> 1);
oldCapacity >> 1 右移运算符 原来长度的一半 再加上原长度也就是每次扩容是原来的1.5倍
之前的所有都是确定新数组的长度,确定之后就是把老数组copy到新数组中,这样数组的扩容就结束了。
以上的一切都是ArrayList扩容的第一步,第二步就没啥说的了,就是把需要添加的元素添加到数组的最后一位。
2. Spring处理相互依赖的bean
- Spring只能解决Setter方法注入的单例bean之间的循环依赖
- ClassA依赖ClassB,ClassB又依赖ClassA,形成依赖闭环。Spring在获取ClassA的实例时,不等ClassA完成创建就将其曝光加入正在创建的bean缓存中。在解析ClassA的属性时,又发现依赖于ClassB,再次去获取ClassB,当解析ClassB的属性时,又发现需要ClassA的属性,但此时的ClassA已经被提前曝光加入了正在创建的bean的缓存中,则无需创建新的的ClassA的实例,直接从缓存中获取即可。从而解决循环依赖问题。
3. 两种代理的区别
JDK代理是不需要以来第三方的库,只要JDK环境就可以进行代理,java动态代理是利用反射机制生成一个实现代理接口的匿名类,它有几个要求
- 实现InvocationHandler
- 使用Proxy.newProxyInstance产生代理对象
- 被代理的对象必须要实现接口
而cglib动态代理是利用asm开源包,是基于类的扩展,为目标类生成一个子类,重写父类的方法。动态代理通过字节码处理框架ASM生成代理类以及代理类的FastClass,能通过FastClass快速找到代理方法,比反射快
也可以强制使用CGlib
在spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>或 @EnableAspectJAutoProxy (proxyTargetClass = true)
4.bean的作用域
使用bean的scope属性来配置bean的作用域
singleton:默认值,容易初始化创建bean的实例,再整个容器的生命周期内只创建这一个bean,单例的。
prototype:原型的,容器初始化时不创建bean的实例,而再每次请求时都创建一个新的bean实例,并返回。
request:每次HTTP请求都会产生一个新得bean,需要注意的是,该作用域仅在基于Web的spring ApplicationContext情形下有,seesion也是。
session:每次会话创建一个实例。