ok
MVC
- Ioc,控制反转,将对象的创建和控制权交给spring,Ioc容器
- AOP的直接体现就是注解
AOP和IOC的理解
- AOP面向切面编程,起到了解耦的作用,完成一个日志/事务/权限处理等不属于业务里的功能,不需要更改过多业务代码,而是通过一个AOP动态代理(JDK/GClib)完成,调用时将公共逻辑添加到项目中
- IOC,控制反转+依赖注入,通过IOC容器控制对象/对象的依赖 的创建,反转是用IOC容器创建后注入到对象中,由主动创建变成了被动创建
- IOC底层实现过程:核心原理是反射,使用BeanFactory的工厂模式实现的
- 反射的方式实例化Bean
- 对象属性用
populateBean
填充,循环依赖使用三级缓存 invokeAwareMethod
,设置相关依赖:BeanName
BeanFactory
BeanClassloader
- 调用
BeanPostProcessor()
前置处理方法,ApplicationContextPostPostProcessor
,设置上下文,环境,resourceloader等对象 - 调用
invokeInitmethod()
,判断是否实现initializingBean
,调用了就再调用afterpropertiesSet
方法 - 调用
BeanPostProcessor
的后置处理方法,AOP在该过程实现,AbstractAutoProxyCreator()
,advice切面切点 - 获取完整的对象,可以用getbean获取了
- 执行完后,销毁流程,先判断是否实现
DisposableBean
接口,再判断是否实现DestroyMethod
接口
循环依赖怎么解决?【使用了三级缓存】
使用了三级缓存,AOP,提前暴露对象
- 问题:对象循环依赖产生的问题,A依赖B,B依赖A,提前暴露对象导致的
- Bean创建流程是先实例化,再进行属性填充初始化
- A如果属性里有B,在填充时需要从IOC容器里查找B,找不到的话,就创建B;然后B在属性填充的时候查找A,但是A没有创建完毕,
- 一级缓存中放的是完整对象,二级是没有完全创建的对象
- 第三级为什么需要?第三级缓存的value类型是ObjectFactory类型的函数接口,保证在整个容器的作用域中只有一个版本的同名Bean对象。
- 创建bean对象后,要放到三级缓存中是用于先判断是否需要被代理,选择取的是普通对象还是代理对象。
如果一个对象需要被代理,需不需要先实例化一个普通对象(要,必须传参数给wrapifnecessary)
普通对象和代理对象不能同时出现在容器中,当需要被代理时,就需要覆盖普通对象
SpringAOP的底层原理
底层原理就是使用的jvm或者gclibs的动态代理功能。AOP的实现阶段是IOC的BeanPostProcessor的后置方法中实现的扩展功能。
- 介绍一下jvm gclib的原理,反射
Spring的设计模式
- Bean都是单例模式
- 工厂模式,BeanFactory
- 观察者模式,Listener,Event
- 适配器模式,Adapter
- 装饰者模式:Bean的Wrapper
- 责任链模式:使用AOP时,先生成一个拦截器
- 代理模式:AOP使用的动态代理
事务
Spring事务如何实现的,如何回滚
答:事务是AOP实现的声明式事务。也就是首先要生成具体的代理对象,按AOP的流程来执行具体操作逻辑。1
2(propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT, readOnly = false, timeout = -1)
底层具体到代码里是用jdbc的datasourceTransactionManager
实现的,注解声明的事务逻辑是通过一个TransationInterceptor
类实现,调用invoke函数体里,最后返回一个invokewithtransaction实现具体逻辑(对传参的方法使用getmethod获取)
- 回滚的方式如下:
- 执行失败使用
completeTransactionAfterthrowing
- 执行成功用
completeTransactionAfterreturning
- 执行失败的回滚在transactional的doRollback里实现,里面是先获取object.getconn连接,然后conn.rollback回滚,只对于这个特定连接进行,而不是全局的。
- 执行成功的提交在transactional里的doCommit,也是获取连接,用jdbc连接的conn.commit()方法提交。
- 最后
cleanTransactionInfo
清除当前事务信息
SpringBoot的优点
- 独立运行
Spring Boot 而且内嵌了各种 servlet 容器,Tomcat、Jetty 等,现在不再需要打成war 包部署到容器中,Spring Boot 只要打成一个可执行的 jar 包就能独立运行,所有的依赖包都在一个 jar 包内。 - 简化配置
spring-boot-starter-web 启动器自动依赖其他组件,简少了 maven 的配置。 - 自动配置
Spring Boot 能根据当前类路径下的类、jar 包来自动配置 bean,如添加一个 spring
boot-starter-web 启动器就能拥有 web 的功能,无需其他配置。 - 无代码生成和XML配置
Spring Boot 配置过程中无代码生成,也无需 XML 配置文件就能完成所有配置工作,这一切都是借助于条件注解完成的,这也是 Spring4.x 的核心功能之一。 - 应用监控
Spring Boot 提供一系列端点可以监控服务及应用,做健康检测Spring Bean
被Ioc容器管理的对象,通过xml或者Entity等注解
org.springframework.beans
org.springframework.context
@Component:通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
@Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。
@Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
@Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面
1. @Bean和@Component的区别
- bean用于方法,component用于注解
- @Component通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。
- @Bean注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我
2. 可以注入Bean的注解有哪些
- @Autowired
- @Resource
Spring事务
Spring 管理事务的方式有几种?
- 编程式事务:在代码中硬编码(不推荐使用) : 通过 TransactionTemplate或者 TransactionManager 手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。
- 声明式事务:在 XML 配置文件中配置或者直接基于注解(推荐使用) : 实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)
1. @Transactional
使用场景:hibernate的删除事务,更新事务
- 使用
@Transactional(rollbackFor = Exception.class)
:- 用于保证事务一致性,发生异常时回滚
- 不配置for exception的话,只有在runtime err时回滚,为了保证可靠性
SpringBoot
- 从常用注解和生命周期,启动,监控,测试等考察
- 是@Configuration、@EnableAutoConfiguration、@ComponentScan的集合体
1. @SpringBootApplication
自动装配原理是什么?
- @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
- @Configuration:允许在上下文中注册额外的 bean 或导入其他配置类
- @ComponentScan:扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。
2. 常用注解:
- @RestController和@Controller指定一个类,作为控制器的注解
- @RequestMapping方法级别的映射注解,这一个用过Spring MVC的小伙伴相信都很熟悉
- @EnableAutoConfiguration和@SpringBootApplication是类级别的注解,根据maven依赖的jar来自动猜测完成正确的spring的对应配置,只要引入了spring-boot-starter-web的依赖,默认会自动配置Spring MVC和tomcat容器
- @Configuration类级别的注解,一般这个注解,我们用来标识main方法所在的类,完成元数据bean的初始化。
- @ComponentScan类级别的注解,自动扫描加载所有的Spring组件包括Bean注入,一般用在main方法所在的类上
- @ImportResource类级别注解,当我们必须使用一个xml的配置时,使用@ImportResource和@Configuration来标识这个文件资源的类。
- @Autowired注解,一般结合@ComponentScan注解,来自动注入一个Service或Dao级别的Bean
- @Component类级别注解,用来标识一个组件,比如我自定了一个filter,则需要此注解标识之后,Spring Boot才会正确识别。