对Spring IOC 的理解
控制反转: 理论思想,原来的对象是由使用者来进行控制,有了spring之后,可以把整个对象交给spring来帮我们进行管理
DI: 依赖注入,把对应的属性的值注入到具体的对象中,@Autowired,完成属性值的注入
容器: 存储对象,使用map结构来存储,在spring中一般存在三级缓存,singletonObjects存放完整的bean对象,整个bean的生命周期,从创建到使用到销毁的过程全部都是由容器来管理(bean的生命周期)
在Spring中,所有bean都是通过反射的方式生成的,ioc中最核心的也就是填充具体bean的属性值和生命周期。
生命周期
springmvc执行流程
- 用户发送请求到前端控制器(DispatcherServlet)。 前端控制器 ( DispatcherServlet )收到请求调用处理器映射器 (HandlerMapping),去查找处理器(Handler)。
- 处理器映射器(HandlerMapping)找到具体的处理器(可以根据 xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给 DispatcherServlet。
- 前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)。
- 处理器适配器(HandlerAdapter)去调用自定义的处理器类(Controller)。
- 自定义的处理器类(Controller)将得到的参数进行处理并返回结果给处理器适配器(HandlerAdapter)。 处理器适配器 (HandlerAdapter )将得到的结果返回给前端控制器 (DispatcherServlet)。
- 前端控制器(DispatcherServlet )将 ModelAndView 传给视图解析器 (ViewResolver)。
- 视图解析器(ViewResolver)将得到的参数从逻辑视图转换为物理视图并返回给前端控制器(DispatcherServlet)。
- 前端控制器(DispatcherServlet)调用物理视图进行渲染并返回。
- 前端控制器(DispatcherServlet)将渲染后的结果返回。
泛型
1、背景
在Java没有泛型概念以前,程序员可以创建一个元素类型为Object的集合,该集合可以存储任意数据类型的对象,而在使用该集合的过程中,程序员需要明确知道存储的每个元素的数据类型,否则很容易引发ClassCastException异常。
2、概念
Java泛型是JDK5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制让我们在编译时就能监测到非法的类型数据结构。
泛型的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。
3、好处
- 类型安全;
- 消除了强制类型转换。
泛型方法
语法:
修饰符 <T,E, …> 返回值类型 方法名(形参列表) { 方法体… }
public static <T> List<T> ArrayByList(T... args){
ArrayList<T> ts = new ArrayList<>();
for (T arg : args) {
ts.add(arg);
}
return ts;
}
*注意:
泛型方法的类型不受该类的泛型影响
泛型的协变(上限)与逆变(下限)
协变(只读不写)
泛型的协变表示该集合不能添加元素,但是可以遍历元素
协变可以接收规定类型和他的子类
类/接口<? extends 实参类型>
逆变(一般只写不读)
泛型的逆变表示该集合可以 添加 该类或者该类的子类
但在遍历时所有元素都变成了Object类型,因此逆变一般不会去读取
逆变可以接收规定类型及其父类
类/接口<? super 实参类型>
应用场景
public static void main(String[] args) {
/***
* 泛型的协变表示该集合不能添加元素,但是可以遍历元素 只读不写
* 协变可以接收规定类型和他的子类
*/
//泛型的协变
List<? extends Animal> dogs = new ArrayList<>();
// dogs.add(new Animal());//--编译时异常
// dogs.add(new Dog());//-----编译时异常
// dogs.add(new Cat());//-----编译时异常
/***
* 泛型的逆变表示该集合可以 添加 该类或者该类的子类
* 但在遍历时所有元素都变成了Object类型
* 逆变可以接收规定类型及其父类
*/
//泛型的逆变
List<? super Animal> list=new ArrayList<>();
// list.add(new Animal());
// list.add(new Dog());
// list.add(new Cat());
// for (Object o : list) {
// Animal o1 = (Animal) o;
// o1.call();
// }
List<萨摩> src = new ArrayList<>();
List<Animal> dest = new ArrayList<>();
src.add(new 萨摩());
src.add(new 萨摩());
src.add(new 萨摩());
src.add(new 萨摩());
src.add(new 萨摩());
copyDagList(dest,src);
System.out.println(dest.size());
}
/***
* List的复制
* @param dest 目标List
* @param src 含有数据的List
*/
public static void copyDagList(List<? super Dog> dest,List<? extends Dog> src){
for (Animal animal : src) {
animal.call();
}
src.forEach(e->dest.add(e));
}
这个copy方法与Collections.copy()方法类似,都是使用了泛型的逆变接收复制的新集合(只需添加不需遍历),泛型的协变接收被复制的集合(只需遍历,不需要增删)
多态
多态就是同类型的对象,执行同一个行为,会表现出不同的行为特征
多态就是同一个接口,使用不同的实例而执行不同操作
多态是开闭原则的体现,对扩展开放,对修改封闭
优点:
缺点:
- 在多态下无法使用使用子类特有的方法
编译时多态
方法的重载
运行时多态
Java运行时系统根据调用该方法的实例的类型来选择调用哪个方法则被称为运行时多态。
运行时多态的三个必要条件
- 要有继承(包括接口的实现);
- 要有重写;
- 父类引用指向子类对象。