Spring学习记录1
- Spring框架核心 IOC & AOP
IoC(Inverse of Control-控制反转):只是一种设计思想,将对象的创建和管理工作交给Spring框架、IoC容器实现
AOP(Aspect-Oriented Programming-面向切面编程):可以将一些非业务逻辑(事务、日志、权限..)嵌入到业务模块当中,以达到去重和解耦的作用,方便拓展
Spring AOP基于动态代理实现,当被代理对象为实现接口形式时,使用JDK Proxy去创建代理对象,对于没有实现接口的被代理对象,使用CGlib生成一个被代理对象的子类来作为代理
Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation),后者的运行效率比前者快很多
-
单例bean的线程安全问题
Spring中的bean默认都是单例(singleton),那么在多线程情况下必然会产生线程安全问题,这样就要求在定义bean对象时避免出现可变成员变量(推荐使用ThreadLocal来保存可变成员变量),另外像Service、Dao这些对象都是无状态(没有实例变量)的,这种情况bean是线程安全的 -
SpringMVC原理
Java Web应用开发演变历程:
Model 1时代:几乎全部由JSP页面组成,少量JavaBean处理数据库连接访问]
==> Model 2时代:Java Bean(Model)+ JSP(View)+Servlet(Controller)]
==> SpringMVC时代:Service 层(处理业务)、Dao 层(数据库操作)、Entity 层(实体类)、Controller 层(控制层,返回数据给前台页面)原理流程图:
①向服务器发送 HTTP 请求,请求被前端控制器 DispatcherServlet 捕获②DispatcherServlet 根据 -servlet.xml 中的配置对请求的 URL 进行解析,得到请求资源标识符(URI)。然后根据该 URI,调用 HandlerMapping 获得该 Handler 配置的所有相关的对象(包括 Handler 对象以及 Handler 对象对应的拦截器),最后以HandlerExecutionChain 对象的形式返回
③DispatcherServlet 根据获得的Handler,选择一个合适的 HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的 preHandler(…)方法)
④提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。在填充Handler的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作:
-
HttpMessageConveter:将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的响应信息。
-
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。
-
数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。
-
数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。
⑤Handler(Controller)执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象;
⑥根据返回的ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的ViewResolver)返回给DispatcherServlet。
⑦ViewResolver 结合Model和View,来渲染视图。
⑧视图负责将渲染结果返回给客户端。
-
-
@Transactional(rollbackFor = Exception.class)注解 --- 该注解如果不配置rollbackFor属性,事务只有在遇到RuntimeException的时候才会回滚,加上 rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚
-
Spring框架用到的设计模式汇总:
-
观察者模式 & Spring事件驱动模型
Spring 事件驱动模型就是观察者模式很经典的一个应用- 观察者模式:
观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
- 事件机制的三个重要组成部分-事件源、事件、事件监听器,对应Spring中的实现:
①事件源 => ApplicationEventPublisher(事件发布接口)中的publishEvent方法发布事件 ,其默认实现AbstractApplicationContext中关键代码如下
protected void publishEvent(Object event, @Nullable ResolvableType eventType) { // 如果可能,现在就进行多播 - 或者在多播器初始化后懒惰地进行 if (this.earlyApplicationEvents != null) { // 暂存事件 this.earlyApplicationEvents.add(applicationEvent); } else { // 获取事件广播器广播事件 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); } }
其中ApplicationEventMulticaster(事件广播器)的广播实现源码如下:
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); // 遍历事件监听器 for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { // 多线程执行监听器onApplicationEvent方法 executor.execute(() -> invokeListener(listener, event)); } else { // 直接执行onApplicationEvent方法 invokeListener(listener, event); } } }
②事件 => ApplicationEvent,可通过继承该类进行扩展
③监听器 => ApplicationListener(用程序事件监听器实现的接口),处理应用程序事件方法onApplicationEvent,可以实现该接口和方法对事件监听器进行扩展Spring事件驱动模型结构:
-
FactoryBean & BeanFactor
FactoryBean是Bean,可以通过实现 FactoryBean 接口定制实例化 Bean 的逻辑,通过代理一个Bean对象,对方法前后做一些操作 -
SpringBean的生命周期
-
Spring如何解决循环依赖问题
Spring解决循环依赖是依赖三级缓存实现,通过三级缓存提前拿未初始化的对象,最终实现基于以下两点:- Spring通过递归方式获取Bean和它所依赖的Bean (doGetBean方法,先是缓存获取,缓存没有则doCreateBean方法创建)
- Spring创建Bean分为两步,首先实例化目标Bean,然后初始化就注入属性
看下doGetBean方法的部分逻辑:
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // 查询三级缓存中的Bean实例 Object sharedInstance = getSingleton(beanName); if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { // 创建Bean实例,并保存到三级缓存(singletonFactories)中 return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } }
getSingleton方法,获取缓存bean实例的具体实现---读取三级缓存:
protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { synchronized (this.singletonObjects) { singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } } } return singletonObject; }
createBean方法的相关实现:这里可以看到实现循环依赖的先决条件有[isSingleton(单例) & allowCircularReferences(开启循环依赖) & allowCircularReferences(对象正在创建)]
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 前面部分代码实现bean的构建 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { // 新增实例到三级缓存 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } }
一级缓存(singletonObjects):用来保存实例化、初始化都完成的对象 二级缓存(earlySingletonObjects):用来保存实例化完成,但是未初始化完成的对象 三级缓存(singletonFactories):用来保存一个对象工厂,提供一个匿名内部类,用于创建二级缓存中的对象
示例:循环依赖A->B,B->A
为什么使用三级缓存而不是二级缓存?
为了生成代理对象,因为三级缓存中放的是生成具体对象的匿名内部类,他可以生成代理对象,也可以是普通的实例对象 -
Spring的事务传播机制
PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,这也是通常我们的默认选择 PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务 PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行 PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起 PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常 PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常 PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行
参考内容:
https://www.cnblogs.com/fingerboy/p/6393644.html
https://javaguide.cn/system-design/framework/spring/spring-design-patterns-summary/
https://mp.weixin.qq.com/s/euzbHPpQG2BSKl93N5L1Hg