IOC DI机制
IOC的意思是控制反转,控制的意思啊由Spring 工厂控制对象,反转是从我们主动创建好对象反转为等待Spring 工厂的注入
DI是依赖注入,组件需要的依赖对象由容器注入,主要通过setter 构造器 接口三种注入方式注入.
Spring如何解决循环依赖
Spring 的循环依赖就是指多个bean之间的依赖关系产生了循环调用,Spring的循环依赖分为3中
- 两个bean之间互相依赖,如bean a依赖bean b ,bean b依赖bean a
- 多个bean之间存在简介的相互调用bean a依赖bean b ,bean b依赖bean c
- bean依赖自己如bean a依赖bean a
Spring是通过三级缓存的方式去解决循环依赖问题的,三级缓存分别代表:
- 一级缓存,用于存放完整的bean实例,一级缓存中的bean实例是可以被直接使用的
- 二级缓存中存放的是已经被初始化,但是还没有进行依赖注入的bean实例
- 三级缓存中存放的BeanFactory工厂,用于生产初始化的bean,并将其放入二级缓存
例如我们现在又两个bean,bean A和bean B,他们相互依赖,那我们解决依赖的方式就是:
- 初始化Bean A,从一级缓存开始查找Bean A,发现A实例不存在,所以会先创建A实例,并放入三级缓存中,此时A实例还并未初始化
- 由于A实例需要注入B实例,所以现在开始初始化B实例,从一级缓存开始查找Bean B,发现B实例不存在,所以会先创建B实例,并放入三级缓存中.由于B实例也需要注入A实例
- 所以现在再从一级缓存开始查找A实例,由于刚刚我们已经创建了A实例,并且将它放到了三级缓存
- 所以我们通过三级缓存中的A BeanFactroy初始化一个A实例,并且放到二级缓存中,同时吧这个A实例注入到B实例中,由于B 实例是一个完整的Bean,所以会放入一级缓存.
- 之后我们从一级缓存中找到了B实例,再将B注入到A中,就完成了A B两个bean 的创建.
AOP 面向切面编程
AOP思想是做无侵入式的功能增强,即在不改变其原有方法代码的情况下,增加一定的功能.AOP是通过代理实现的.
Spring中AOP的核心是动态代理,jdk动态代理或CGLIB代理.
AOP分为:
- 前置通知
- 后置通知
- 后置返回值通知
- 异常通知
- 环绕通知
AOP的实现步骤
- 首先定义一个切面,创建一个类,在类上添加注解Aspect
- 生命一个方法,定一个那些方法需要被织入,使用Pointcut注解
- 定义增强操作,如前置通知 @Befare 后置通知@After 等等.
- 建立切面与切点之间的关联
@Aspect
@Component
public class LogAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// 定义切点,对所有 public 方法进行拦截
@Pointcut("execution(public * com.example..*.*(..))")
public void logPointcut() {}
// 定义前置通知,在目标方法执行前执行
@Before("logPointcut()")
public void beforeAdvice(JoinPoint joinPoint) {
logger.info("beforeAdvice: " + joinPoint.getSignature().getName());
}
// 定义后置通知,在目标方法执行后执行
@AfterReturning("logPointcut()")
public void afterAdvice(JoinPoint joinPoint) {
logger.info("afterAdvice: " + joinPoint.getSignature().getName());
}
// 定义异常通知,在目标方法抛出异常时执行
@AfterThrowing(pointcut = "logPointcut()", throwing = "ex")
public void throwingAdvice(JoinPoint joinPoint, Exception ex) {
logger.error("throwingAdvice: " + joinPoint.getSignature().getName() + " occurs an exception, exception message is: " + ex.getMessage());
}
}
Aop的使用场景
1.事务管理,通过Aop的方式,将事务的开启提交及回滚放在Aop中,这样可以减少代码冗余
2.日志打印,通过Aop的方式,在部分函数的执行过程加入log打印,方便了解程序运行过程和error记录
3.性能监控,可以通过Aop获取代码的执行时间,了解其执行速度,方便提高效率
4.安全检查,使用Aop进行权限检查,身份验证等功能
5.缓存管理,可以缓存经常被调用的数据,条响应速度
6.异常处理,将一些通用的异常处理剥离出来,方在aop中实现,可以减少代码冗余
Spring MVC执行流程
1.客户端向服务器发起请求
2.当请求到达后端之后,所有的请求都会被dispatchServlet拦截,dispatchServlet会调用HandlerMapping,
3.HandlerMapping会根据请求的url去解析应该将请求转发到哪个控制器中,如果没有找到对应的控制器,会返回404
4.HandlerAdapter会在HandlerMapping确定好应该发给哪个控制器之后去将该请求转发给对应的控制器
5.控制器收到请求之后将会处理该请求,返回一个视图和模型对象
6.视图解析器将视图渲染成响应并转发给客户端
7.客户端接收到请求.
Spring Boot自动装配原理
从启动类上的注解一步步推吧
Spring Boot 的启动类上需要添加@SpringBootApplication注解,看一下它的源码
这里可以看到有两个注解,@SpringBootConfiguration 和 @EnableAutoConfiguration ,先看一下@SpringBootConfiguration
@SpringBootConfiguration
查看它的源码,可以看到它上面包含了注解@Configuration,其中又包含了@Component
也就是说添加了注解@Configuration或者SprigBootConfiguration的类都会成为SpringBoot的配置类,交给容器同一管理.
@EnableAutoConfiguration
这个注解的作用在于开启自动配置的功能,其中包含了两个注解@AutoConfigurationPackage,和@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage
这个注解的作用在于将主配置类,即添加了SpringBootApplication注解的启动类所在的包及包下包含的所有中间扫描并加载到spring工厂中.
@Import(AutoConfigurationImportSelector.class)
这个注解的作用是将需要自动装配的类以全类名的方式返回.在类AutoConfigurationImportSelector中存在一个方法selectImports,其中调用了getAutoConfigurationEntry方法
又依次调用了getCandidateConfigurations方法,loadFactoryNames方法,loadSpringFactories方法.
loadSpringFactories方法会扫描所有在META-INF路径下的spring.factories文件
Spring Cloud 五大组件
Eureka,负责注册和管理服务.
Ribbon,负责负载均衡,平衡服务间的压力
Hystrix,负责熔断和请求降级处理.
Zuul,网关处理,路由
Config,将配置文件整合起来放到远程仓库,方便管理
分布式和微服务的区别
分布式和微服务是两个不同的概念
分布式是只多个独立计算机组成的系统,通过计算机网络相互通信互补完成整个系统功能
微服务是一种架构思想,是分布式系统的一种实现方式,通过将单个微型服务作为一个独立的项目,最终搭建微服务项目群,通过项目间的轻量级通讯,相互配合最终完成整个负责的业务流程.
相对于传统的软件架构来说,微服务具有高可扩展性,高灵活性的特点.总的来说,微服务是分布式的一种实现方式,但是分布式除微服务外还有许多种实现方式,如:RPC通信,消息队列,分布式缓存,分布式文件系统等.