1.什么是Spring IOC 和 DI ?
- 控制反转(IOC): Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可, 这就是控制反转的思想。将创建对象,销毁对象的权利交给Spring容器,解除类与类之间的耦合。
- 依赖注入(DI): Spring使用Java Bean对象的set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置成所需要的值的过程就是依赖注入的基本思想。
2.AOP的理解
底层使用的是动态代理;使用配置的方式来完成动态代理要实现的功能。
在不修改源码的基础上,对目标对象中方法进行增强。实现业务之间解耦。
切入点:目标对象中要被增强的方法。
通知: 要增强的功能。
连接点:目标对象中可以被增强的方法。
切面:切入点和通知的组合。
@Slf4j
@Component
@Aspect
public class AutoFillAspect {
/**
* 设置切入点
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut() {}
/**
* 前置通知,在通知中进行公共字段的赋值
* @param joinPoint
*/
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint) {
log.info("开始进行公共字段自动填充...");
//获取到当前被拦截的方法上的数据库操作类型
MethodSignature signature = (MethodSignature)joinPoint.getSignature(); //方法签名对象
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class); //获得方法上的注解对象
OperationType operationType = autoFill.value(); //获得注解上的数据库操作类型
//获取到当前被拦截的方法的参数---实体对象
Object[] args = joinPoint.getArgs();
//防止出现空指针异常
if (args == null || args.length == 0) {
return;
}
//获取到实体对象
Object entity = args[0];
//准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//根据当前不同的操作类型,为对应的属性通过反射来赋值
if (operationType == OperationType.INSERT) {
//为4个公共字段赋值
try {
//利用实体类的字节码对象,获取当前类中的公开方法对象
Method setCreateTime = entity.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
//通过反射为对象属性赋值
setCreateTime.invoke(entity, now);
setCreateUser.invoke(entity, currentId);
setUpdateTime.invoke(entity, now);
setUpdateUser.invoke(entity, currentId);
} catch (Exception e) {
e.printStackTrace();
}
} else if (operationType == OperationType.UPDATE) {
//为2个公共字段赋值
try {
//利用实体类的字节码对象,获取当前类中的公开方法对象
Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
//通过反射为对象属性赋值
setUpdateTime.invoke(entity, now);
setUpdateUser.invoke(entity, currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
3.SpringAOP代理方式有几种,怎么配置,实现原理是什么?
- JDK动态代理:目标类必须实现一个接口,代理类和目标类实现相同的接口。JDK动态代理只能对实现了接口的类生成代理,而不能针对类
- CGLIB动态代理:目标类不能是最终类。Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 进行增强,但是因为采用的是继承,所以该类或方法最好不要声明为final,对于 final类或方法,是无法继承的。
4.Spring常用的注解?
IOC相关注解:
- 创建bean的注解: @Component @Controller @service @Repository
- 依赖注入的注解: @Autowired @Qualifier @value
- 作用范围的注解:@Scope("singleton | proptotype")
- 配置类,组件扫描,加载配置文件:
@Configuration
@Bean
@Component
@Import
@PropertySource("classpath: a.properties")
AOP相关注解:
@EnableAspectJAutoProxy 开启AOP
事务相关注解:
@EnableTransactionManagement 开启声明式事务
@Transactional
异步任务:
@EnableAsync 开启异步任务
@Async
定时任务:
@EnableScheduling 开启定时任务
@Scheduled
缓存:
@EnableCaching 开启Spring Cache
@Cacheable : 先判断缓存中是否有数据,有就返回,没有就执行方法 将方法的返回值存入缓存。
@CacheEvict: 执行完方法,从缓存中删除数据
@CachePut: 执行完方法,向缓存中存数据
5.@Autowired 和 @Resource 区别?
区别:
@Autowired 是 spring提供的注解。
@Resource 是JDK在jsr250中定义的注解
功能:
@Autowired 是按照类型注入。如果有多个bean的类型和属性的类型是一样的,可能会报错。
@Autowired 结合@Qualifier 按照名称注入
@Resource单个注解就可以实现按照名称注入 等价于 @Autowired + @Qualifier
6.spring BeanFactory和FactoryBean区别 ?
BeanFactory: 整个IOC容器的顶层接口,ApplicationContext是他的子接口。
FactoryBean: 通过工厂模式,将对象放入IOC容器的一种方式
7.简述spring bean的生命周期(比较浅显的分析)
bean的生命周期:bean什么时候被创建,bean什么时候被销毁。
实例化:
1.如果仅仅只有一个构造方法,使用该构造方法创建对象。
2.如果有多个构造方法,使用无参构造方法创建对象,如果没有无参构造,报错。
3.构造方法即使是私有的,也能实例化。
属性填充:
1.通过依赖注入,给对象的属性赋值。
2.如果类实现了Aware相关接口,spring也会调用相应方法。
初始化:
1.初始化之前会调用BeanPostProcessor的before方法
2.调用对象初始化方法。
3.初始化之前会调用BeanPostProcessir的after方法
4.spring自带BeanPostProcessor可以生成代理对象
销毁:
IOC容器关闭
IOC容器中单例bean就会被销毁,销毁之前还会调用销毁方法
Spring容器关闭时调用DisposableBean中destory()方法
8.Spring支持的几种bean的作用域
Spring框架支持以下五种bean的作用域:
singleton: bean在每个Spring IOC 容器中只有一个实例。
prototype: 一个bean的定义可以有多个实例。
request: 每次http请求都会创建一个bean,该作用域仅在基于web的SpringApplicationContext情形下有效。
session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
application: 属于应用程序域,应用程序启动时bean创建,应用程序销毁时bean销毁。该作用域仅在基于web的ServletContext
9.spring事务什么时候会失效?
因为Spring事务是基于代理来实现的,所以某个加了@Transactional的方法只有是被代理对象调用时,那么这个注解才会生效,如果使用的是目标对象调用,那么@Transactional会失效。
同时如果某个方法是private的,那么@Transactional也会失效,因为底层cglib是基于父子类来实现的,子类是不能重载父类的private方法的,所以无法很好的利用代理,也会导致@Transactional失效。
如果在业务中对异常进行了捕获处理,出现异常后Spring框架无法感知到异常,@Transactional也会失效。
@Transactional中的配置的Rollback的默认是异常是:runTimeException更改为 Exception
10.什么是Spring的循环依赖?
简单的来说就是A依赖B的同时,B依赖A。在创建A对象的同时需要使用的B对 象,在创建B对象的同时需要使用到A对象。
Spring解决循环依赖是通过三级缓存:
- 一级缓存:singletonObjects
作用是:单例池; 缓存已经经历了完整生命周期, 已经初始化 完成的bean对象
2. 二级缓存:earlySingletonObjects
作用是:缓存早期的bean对象(生命周期还没有走完)
3. 三级缓存:singletonFactories
作用是:缓存的是ObjectFactory, 表示对象工厂, 用来创建某个对象的
步骤如下所示:
1、实例化A,得到原始对象A,并且同时生成一个原始对象A对应的 ObjectFactory对象
2、将ObjectFactory对象存储到三级缓存中
3、需要注入B,发现B对象在一级缓存和二级缓存都不存在,并且三级缓存中也 不存在B对象所对应的ObjectFactory对象
4、实例化B,得到原始对象B,并且同时生成一个原始对象B对应的 ObjectFactory对象,然后将该ObjectFactory对象也存储到三级缓存中
5、需要注入A,发现A对象在一级缓存和二级缓存都不存在,但是三级缓存中存 在A对象所对应的ObjectFactory对象
6、通过A对象所对应的ObjectFactory对象创建A对象的代理对象
7、将A对象的代理对象存储到二级缓存中
8、将A对象的代理对象注入给B,B对象执行后面的生命周期阶段,最终B对象创 建成功
9、将B对象存储到一级缓存中
10、将B对象注入给A,A对象执行后面的生命周期阶段,最终A对象创建成功, 将二级缓存的A的代理对象存储到一级缓存中
11.SpringMVC工作流程
前后端分离开发,后端响应json
- 浏览器发送请求,localhost:8888/xxx 请求先到前端控制器(DispatcherServlet)
- 前端控制器调用处理器映射器,根据请求url查找Handler,处理器映射器将Handler和拦截器封装HandlerExecutionChain返回前端控制器。
- 前端控制器调用处理器适配器,执行拦截器中方法和Handler
- 将返回值返回前端控制器
- 将返回值转化为JSON字符串响应给前端。
12.SpringBoot提供了哪些核心功能?
- 起步依赖:Spring boot 将各种场景的依赖包,制作成一个个的starter,我们在项目中只需要引入对应场景的起步依赖,就可以引入该场景所有的依赖包。
- 自动装配:只需要在项目中引入起步依赖,spring boot将该场景相关bean交给spring管理,我们只需要在程序中注入对应的bean即可。
- 辅助功能(内嵌tomact,健康检测)
13.Springboot的常用注解?
14.Springboot自动装配原理?
Springboot主启动类的注解 @SpringbootApplication中有一个自动配置注解@EnableAutoConfiguration,这个注解底层使用了@Import注解导入AutoConfigurationImportSelector 的实现类,实现类中的方法selectImports中扫描了 spring.factories 和 AutoConfiguration.imports这两个配置文件,配置文件中有许多的自动配置类,自动配置类中就使用@Bean注解把对象放到了Spring容器中。
15.Springboot常用的starter有哪些?
- spring-boot-starter-web(嵌入tomcat和web开发需要servlet与 jsp支持)
- spring-boot-starter-data-elasticsearch(es支持)
- spring-boot-starter-data-redis(redis支持)
- spring-boot-starter-amqp(消息队列支持)
- spring-boot-starter-data-mongodb (mongodb的支持)
- mybatis-plus-boot-starter (mybatis plus的支持)
- mybatis-spring-boot-starter (mybatis的支持)
16.Springboot有哪几种读取配置的方式?
1. @value
2. Environment接口
3. @ConfigurationProperties
17.什么是springcloud?
18.分布式锁解决方案
19.springcloud核心组件及其作用