Spring
是一个IOC和AOP的轻量级容器框架
IOC
-
控制反装:对象交由Spring来创建,通过DI依赖注入来实现IOC,原理是工厂模式+反射机制
- ApplicationConext是BeanFactory的子接口,主要用来生成bean
- 反射机制:在程序运行过程中,动态的获取类的属性和对象,如class.forName获取数据库驱动
-
依赖注入方式:构造方法注入,Setter注入,工厂方式注入
-
Bean的装配方式:xml配置,注解@,javaConfig
-
代理模式:把对象包装起来,对对象的调用都要经过这个包装类
-
静态代理:在多态的形式上给实现类创建一个代理类,有重复编码的问题
- 多态:同一类对象调用同一个方法表现出不同的行为特征
- 继承/实现;父类引用指向子类对象;方法重写
-
动态代理:在程序运行过程中,通过反射机制动态创建代理类,比如AOP
-
IOC加载过程/Bean的生命周期
- 首先实例化一个ApplicationContext对象,通过Bean工厂扫描解析类的信息,保存到一个BeanDeifination对象里,然后通过构造方法反射实例化一个对象,进行属性注入,注入完成后根据Bean的类型去调用生命周期接口方法完成初始化操作,如果实现了AOP,就创建动态代理,到此bean创建完成,放到spring容器里,spring容器关闭,bean就销毁了
- BeanDeifination是Bean的定义,包含了类的所有信息,属性,类型,作用域等
- Bean的类型:BeanNameAware,BeanFactoryAware
-
BeanPostProcessor:后置处理器,是Spring IOC容器提供的一个扩展接口,有两个抽象方法,可以在bean初始化方法调用前后做一些逻辑处理
-
Bean创建细节
/** * 1) 对象创建: 单例/多例 * scope="singleton", 默认值, 即 默认是单例 【service/dao/⼯具类】 线程不安全 * scope="prototype", 多例; 【Action对象】 * 2) 什么时候创建? * scope="prototype" 在⽤到对象的时候,才创建对象。 * scope="singleton" 在启动(容器初始化之前), 就已经创建了bean,且整个应⽤只有⼀个。 * 3)是否延迟创建 * lazy-init="false" 默认为false, 不延迟创建,即在启动时候就创建对象 * lazy-init="true" 延迟初始化, 在⽤到对象的时候才创建对象(只对单例有效) */
AOP
-
面向切面编程,就是分离关注点,在不改变源代码的情况下动态的给程序添加一些功能,实质上就是拦截对象方法,对方法进行改造,增强,比如日志,事务,这些都是相同逻辑的重复代码,可以横向抽取出来,用动态代理把这些重复代码织入到目标对象方法中,实现和原来⼀样的功能,这样我们在写业务的时候只需要关心业务代码
-
AOP术语
- 连接点(Join point):能够被拦截的地⽅:Spring AOP是基于动态代理的,所以是⽅法拦截的
- 增强/通知(Advice):5种Advice
- 织⼊(Weaving):将 增强/通知 添加到目标类的具体连接点上的过程
-
AOP的实现者
-
SpringAOP
-
Spring AOP构建在动态代理基础之上,所以,Spring对AOP的支持局限于方法拦截
-
在Java中动态代理有两种方式
- Spring AOP默认是JDK动态代理,他实现的是某个接口
- 多例使用JDK,因为他创建代理对象的性能比CGLib高
-
CGLib动态代理
- 如果没有接口,可以用CGLib,他生成的动态代理对象是目标类的子类
- 单例使用CGLib,生成代理对象的性能比JDK高
-
提供了3种类型的AOP支持
- 基于代理的,需要实现接口,手动创建代理
- 纯POJO切面,使用xml配置,aop命名空间
- @AspectJ注解驱动的切面
-
-
AspectJ
- 静态织入,支持编译时、编译后和类加载时织入,有专门的编译器,SpringAOP只能在运行时织入,不需要编译器
- AspectJ支持所有切入点,SpringAOP只支持方法执行切入点
-
JBoss AOP
-
-
常用注解
- @Aspect:定义一个切面类
- @Component:让类交由Spring管理
- @Pointcut:定义一个切面,即某件事的入口(常用的表达式:execution)
- @Before:在做某件事之前做的事;前置通知
- @After:在做某件事之后做的事;后置通知
- @AfterReturning:在做完某件事之后,对其返回值做增强处理;返回通知
- @AfterThrowing:在做某件事抛出异常时,处理;异常通知
- @Around:环绕通知
-
流程:解析切面,创建动态代理对象,调用方法
-
作用:记录请求URL,参数,流水号,返回值,处理时间等
SpringMVC
-
基本流程
- 用户请求url地址
- 前端控制器dispatcherServlet(接收请求,响应结果)根据url信息和HandlerMapper映射地址去找到相应的Controller
- Controller处理完成后返回一个ModelAndView
- dispatcherServlet根据返回的试图名去调用试图解析器去解析成真正的view,加渲染返回给浏览器
-
SpringMVC是单例模式,在多线程访问时会有线程安全问题
- 在控制器中不使用实例变量(全局变量),线程安全问题归根结底就是数据共享
- 将控制器的作用域从单例改为原型,scope="prototype",每次都会创建新的Controller
- 在控制器中使用ThreadLoacl维护变量
-
SpringMVC的注解
-
@RestController = @Controller+@ResponseBody
-
@Controller 定义一个controller类
-
@RequestMapping:请求映射的注解
- @RequestParam:获取请求参数(是从request上获取参数值);@PathVariable(是从url上获取参数值)
-
@RequestBody:把接收的Json转换成Java对象
-
@ResponseBody:把Java对象转成Json响应给用户
-