Spring
如何选择框架
- 对应的开发者社区是否有名、活跃
- 框架的模块是否不断迭代
Spring IOC
IOC(Inversion of Control):控制反转
- Spring Core最核心部分
- 依赖注入(Dependency Inversion)
- Setter
- Interface
- Constructor
- Annotation
- 避免在各处使用new来创建类,并且可以做到统一维护
- 创建实例的时候不需要了解其中的细节
BeanDefintion
- 主要用来描述Bean的定义
BeanDefintionRegistry
- 提供向IOC容器注册BeanDefintion对象的方法
BeanFactory:Spring框架最核心的接口
- 提供IOC的配置机制
- 包含Bean的各种定义,便于实例化Bean
- 建立Bean之间的依赖关系
- Bean生命周期的控制
BeanFactory与ApplicationContext的比较
- BeanFactory是Spring框架的基础设施,面向Spring
- ApplicationContext面向使用Spring框架的开发者
ApplicationContext的功能
- BeanFactory:能够管理、装配Bean
- ResourcePatternResolver:能够加载资源文件
- MessageSource:能够实现国际化等功能
- ApplicationEventPublisher:能够注册监听器,实现监听机制
getBean方法的代码逻辑
- 转换beanName
- 从缓存中加载实例
- 实例化bean
- 检测parentBeanFactory
- 初始化依赖的Bean
- 创建Bean
Spring Bean的作用域
- singleton:Spring的默认作用域,容器里拥有唯一的Bean实例
- prototype:针对每个getBean请求,容器都会创建一个Bean实例
- request :会为每个HTTP请求创建一个Bean实例
- session:会为每个全局Http Session创建一个Bean实例
- globalSession:会为每个全局Http Session创建一个Bean实例,该作用域仅对Portlet有效
Spring AOP
- 关注点分离:不同的问题交给不同的部分去解决
- 通用化功能代码的实现,对应的就是所谓的切面(Aspect)
- 业务功能代码和切面分开后,架构将变得高内聚低耦合
- 确保功能的完整性:切面最终需要被合并到业务中(Weave)
AOP的主要名词概念
- Aspect:通用功能的代码实现
- Target:被织入Aspect的对象
- Join Point:可以作为切入点的机会,所有方法都可以作为切入点
- Pointcut:Aspect实际被应用在的Join Point,支持正则
- Advice:类里的方法以及这个方法如何织入到目标方法的方式
- Weaving:Aop的实现过程
AOP的实现:JdkProxy和Cglib
- 由AopProxyFactory根据AdvisedSupport对象的配置来决定
- 默认策略如果目标类是接口,则使用JdkProxy来实现,否则使用后者
- JdkProxy的核心:InvocationHandler接口和Proxy类
- Cglib:以继承的方式动态生成目标类的代理
AOP的三种织入方式
- 编译时织入:需要特殊的Java编译器,如AspectJ
- 类加载时织入:需要特殊的Java编译器,如AspectJ和AspectWerkz
- 运行时的织入:Spring采用的方式,通过动态代理的方式,实现简单
Advice的种类
- 前置通知(Before):在方法调用之前执行
- 后置通知(AfterReturning):在方法正常调用之后执行
- 异常通知(AfterThrowing):如果在方法调用过程中发生异常,则通知
- 最终通知(After):在方法调用之后执行
- 环绕通知(Around):在方法调用之前和之后,都分别可以执行通知
切面表达式
- execution代表所要执行的表达式主体
- 第一处 代表方法返回类型代表所有类型
- 第二处 包名代表aop监控的类所在的包
- 第三处 ..代表该包以及其子包下的所有类方法
- 第四处 代表类名,代表所有类
- 第五处 (..)代表类中的方法名,(..)表示方法中的任何参数
- 代码示例:
@Aspect @Component public class ServiceLogAspect { public static final Logger log = LoggerFactory.getLogger(ServiceLogAspect.class); @Around("execution(* com.imooc.service.impl..*.*(..))") public Object recordTimeLog(ProceedingJoinPoint joinPoint) throws Throwable { log.info("===========开始执行{}.{}=========", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName()); // 记录开始时间 long begin = System.currentTimeMillis(); // 执行目标service Object result = joinPoint.proceed(); // 记录结束时间 long end = System.currentTimeMillis(); long takeTime = end - begin; if (takeTime > 3000) { log.error("============执行结束,耗时:{}毫秒======", takeTime); } else if (takeTime > 2000) { log.warn("============执行结束,耗时:{}毫秒======", takeTime); } else { log.info("============执行结束,耗时:{}毫秒======", takeTime); } return result; }
Spring里的代理模式的实现
- 真实实现类的逻辑包含在了getBean方法里
- getBean方法返回的实际上是Proxy的实例
- Proxy实例是Spring采用JDK Proxy或CGLIB动态生成的