上一篇:9. Spring 底层原理
文章目录
- 1. 对Spring的IOC机制的理解
- 2. 对spring的AOP机制的理解
- 3. 了解过cglib动态代理吗?他跟jdk动态代理的区别是什么?
- 4. 能说说Spring中的Bean是线程安全的吗?
- 5. Spring的事务实现原理是什么?能聊聊你对事务传播机制的理解么?
- 6. 画一张图说说spring boot的核心框架?
- 7. 画一张图说说spring的核心框架?
- 8. Spring中使用了哪些设计模式
- 9. 能说一说springMvc的核心架构么?
1. 对Spring的IOC机制的理解
-
IOC叫控制反转其目的就是为了降低程序的耦合性,这是一种设计思想。IOC 控制反转 意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
- 存在一个类 myServiceImpl 实现了 myService 接口,如果在代码中大量使用 new 的方式直接创建了一个 myServiceImpl 对象进行使用,那这些直接使用的地方就和 myServiceImpl 类直接耦合在一起了
- 若此时不想使用 myServiceImpl ,想要换为 newMyServiceImpl (同样实现 myService),那就需要对所有直接使用的地方进行修改,并且需要重新测试
- 如上述示例所说,如果代码中各个类完全耦合在一起,出现任何一点变动,都需要修改大量代码,非常复杂
- 使用 IOC 机制后,实例都是由容器创建的,所以在修改的话,只需要修改注册到容器中的类即可
-
Spring 容器,根据 XML/注解的配置实例化 Bean 对象,然后再根据 XML/注解,对 Bean 之间的引用关系进行依赖注入,让类与类之间彻底解耦,维护代码的时候可以更加轻松
-
底层的核心技术就是反射。利用反射直接根据你的类去构建对应的对象。
-
依赖注入(Dependency Injection,DI)由容器动态的将某个依赖关系注入到组件之中。
2. 对spring的AOP机制的理解
-
AOP(Aspect-Oriented Programming:面向切面编程),能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
-
AOP 使用场景 : 日志系统 、安全统一效验、事务
-
Spring AOP就是基于动态代理的,
-
通过以下简单示例,简述基本原理:
- 原先有这样一个方法:
对这个方法的切面进行编程
public class MyServiceAImpl implements MyServiceA{ public void doServiceA(){ …… } }
- 动态代理后,会生成一个代理对象
将原对象注入进来,并且重写方法,将切面中定义的操作加在方法中相应的位置
public class ProxyMyServiceA implements MyServiceA{ privice MyServiceA myServiceA; public void doServiceA(){ // 切面封装的方法 // 调用执行原本的方法 myServiceA.doServiceA(); // 切面封装的方法 } }
- 调用 MyServiceA 的地方
此时调用的地方注入的不再是原始的 MyServiceImpl ,而是代理对象 ProxyMyServiceA
public class MyControllerA{ @Autowired privice MyServiceA myServiceA; }
- 原先有这样一个方法:
3. 了解过cglib动态代理吗?他跟jdk动态代理的区别是什么?
- 动态代理:其实就是动态的创建一个代理类,并创建这个代理类的实例对象,在这个里面引用原来类的方法,然后所有方法的调用,都是先走代理类的对象,代理类负责做一些代码上的增强
- Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理
- JDK 动态代理:
- 目标类实现了某个接口时使用
- 生成一个代理类,这个代理类会实现和原视类同样的接口,然后通过反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起
- CGLIB 动态代理:
- 目标类没有实现任何接口时使用
- 会在运行时动态的生成目标类的一个子类对象,然后覆盖其中特定方法并添加增强代码
4. 能说说Spring中的Bean是线程安全的吗?
-
Spring 容器中的 Bean 的 五种作用域,(绝大部分的时候,使用的都是单例的)
- singleton : 单例,默认作用域,容器中只有一个 Bean 实例,单例的。
- prototype : 原型,原型每次请求都会创建一个 新的bean实例。
- request : 请求,每一次HTTP请求都会产生一个新的bean,该bean仅 在当前HTTP request内有效。
- session : 会话,每一次HTTP请求都会产生一个新的bean, 该bean仅在当前HTTP session内有效。
- global-session : 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。Portlet是 能够生
-
Spring 中的 Bean 本身是线程不安全的,但是存在以下几种情况下,可以是线程安全的。
- 如上图,Tomcat 会使用多个线程并发的去处理多个请求,这些线程并发的访问多个组件,因为大多使用的是单例的 Bean ,所以这些请求会访问到同一个实例对象中,如果在该对象中存在写操作,此时就是线程不安全的
- 但是以下几种情况下,也可以是线程安全的
- 不存在对内存数据的写操作
- 通过各个组件的互相调用,最终访问到数据库
- 代码中使用了线程安全的数据结构、方法
5. Spring的事务实现原理是什么?能聊聊你对事务传播机制的理解么?
-
事务的实现原理:
- 如果在方法上加了 @Transactional 注解
- 此时 Spring 会采用 AOP 的思想拦截注解,在方法执行前开始事务,在方法执行完成后,根据执行结果来决定是回滚还是提交
-
事务传播机制
-
方法A 和 方法B 都使用了 @Transactional 注解,并且在 A 中调用了 B, 此时就涉及到事务的传播机制
-
7 中事务的传播机制/级别
支持当前事务的情况:
- TransactionDefinition.PROPAGATION_ REQUIRED:(默认使用)
- 如果当前存在事务, 则加入该事务;(也即: 开启事务 -> 执行方法A -> 执行方法 B -> 提交/回滚 )
- 如果当前没有事务,则创建一个新的事务。
- TransactionDefinition.PROPAGATION_ SUPPORTS:
- 如果当前存在事务,则加入该事务;
- 如果当前没有事务,则以非事务的方式继续运行。
- TransactionDefinition.PROPAGATION_ MANDATORY:
- 如果当前存在事务,则加入该事务;
- 如果当前没有事务,则抛出异常。(mandatory: 强制性)
- TransactionDefinition.PROPAGATION_ REQUIRES_ NEW:
- 创建一个新的事务。
- 创建一个新的事务。
- TransactionDefinition.PROPAGATION_ NOT_ SUPPORTED:
- 以非事务方式运行
- TransactionDefinition.PROPAGATION_ NEVER:
- 以非事务方式运行,如果当前存在事务,则抛出异常。:
- TransactionDefinition.PROPAGATION_ NESTED:
- 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_ REQUIRED。
- 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_ REQUIRED。
- TransactionDefinition.PROPAGATION_ REQUIRED:(默认使用)
-
6. 画一张图说说spring boot的核心框架?
- Spring Boot 是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重xml的配置,提供了各种启动器,在运行过程中自定配置。
- Spring Boot 启动时会启动内嵌的 Tomcat,并且将 Spring MVC、Mybatis …… 核心组件自动注入进容器。当需要使用到这些组件时,直接使用容器中的组件
7. 画一张图说说spring的核心框架?
- 使用 BeanDefinitionReader 接口读取 Bean 的基本信息
- 读取 Bean 的定义信息,在读取之前可以通过 BeanFactoryPostProcesser 修改一些 Bean 的定义信息
- 对象工厂(BeanFactory)通过反射的方式获取 Bean 的实例化对象,在类实例化的过程中,可以自定义很多 BeanPostProcesser,来完整 Bean 的实例化,增强某些功能,这些就是 Spring 容器对象
8. Spring中使用了哪些设计模式
- 工厂设计模式 : 把一个对象的创建过程封装到一个工厂里
- Spring 使用工厂模式通过 BeanFactor 创建 bean 对象。
- Spring 本身就是一个大工厂,把所有的 Bean 实例都放在容器里,需要用到的时候,不用创建,直接去容器里获取就好
- 代理设计模式 : Spring AOP 功能的实现。通过动态代理增强切面
- 单例设计模式 : Spring 中的 Bean 默认都是单例的。
- 模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
- 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
- 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
- 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。