对技术人来说,面试成功的道路只有一条,就是好好准备技术基础。本文是面试系列文章Spring篇,作者把自己的八股文和一些经验总结汇总在一起,供大家参考。说的太多了,看起来也比较累,需要最新大厂真题集的朋友可以评论“666”。
设计思想&Beans
1、IOC 控制反转
IoC(Inverse of Control:控制反转)是⼀种设计思想,就是将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。IoC 在其他语⾔中也有应⽤,并⾮ Spring 特有。 IoC 容器是 Spring⽤来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。这样可以很⼤程度上简化应⽤的开发,把应⽤从复杂的依赖关系中解放出来。IoC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。DI 依赖注入DI:(Dependancy Injection:依赖注入)站在容器的角度,将对象创建依赖的其他对象注入到对象中。2、AOP 动态代理
AOP(Aspect-Oriented Programming:⾯向切⾯编程)能够将那些与业务⽆关,却为业务模块所共同调⽤的逻辑或责任(例如事务处理、⽇志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接⼝,那么Spring AOP会使⽤JDKProxy,去创建代理对象,⽽对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代理了,这时候Spring AOP会使⽤基于asm框架字节流的Cglib动态代理 ,这时候Spring AOP会使⽤ Cglib ⽣成⼀个被代理对象的⼦类来作为代理。3、Bean生命周期
单例对象: singleton 
总结:
四个阶段
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
销毁 Destruction
影响多个Bean
- BeanPostProcessor
InstantiationAwareBeanPostProcessor
- 影响单个Bean
Aware
实例化一个Bean--也就是我们常说的new;
按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;
如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,也就是根据就是Spring配置文件中Bean的id和name进行传递;
如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现setBeanFactory(BeanFactory)也就是Spring配置文件配置的Spring工厂自身进行传递;
如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,和4传递的信息一样但是因为ApplicationContext是BeanFactory的子接口,所以更加灵活;
如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization()方法,BeanPostProcessor经常被用作是Bean内容的更改,由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;
如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(),打印日志或者三级缓存技术里面的bean升级;
以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。
- 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,或者根据spring配置的destroy-method属性,调用实现的destroy()方法
4、Bean作用域

在Bean对象中尽量避免定义可变的成员变量(不太现实);
在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中;
5、循环依赖
循环依赖其实就是循环引用,也就是两个或者两个以上的 Bean 互相持有对方,最终形成闭环。比如A 依赖于B,B又依赖于ASpring中循环依赖场景有: prototype 原型 bean循环依赖
构造器的循环依赖(构造器注入)
Field 属性的循环依赖(set注入)
其中,构造器的循环依赖问题无法解决,在解决属性循环依赖时,可以使用懒加载,spring采用的是提前暴露对象的方法。

Spring容器初始化ClassA通过构造器初始化对象后提前暴露到Spring容器中的singletonFactorys(三级缓存中)。
ClassA调用setClassB方法,Spring首先尝试从容器中获取ClassB,此时ClassB不存在Spring 容器中。
Spring容器初始化ClassB,ClasssB首先将自己暴露在三级缓存中,然后从Spring容器一级、二级、三级缓存中一次中获取ClassA 。
获取到ClassA后将自己实例化放入单例池中,实例 ClassA通过Spring容器获取到ClassB,完成了自己对象初始化操作。
这样ClassA和ClassB都完成了对象初始化操作,从而解决了循环依赖问题。
Spring注解
1、@SpringBoot
声明bean的注解@Component 通⽤的注解,可标注任意类为 Spring 组件@Service 在业务逻辑层使用(service层)@Repository 在数据访问层使用(dao层)@Controller 在展现层使用,控制器的声明(controller层)注入bean的注解@Autowired:默认按照类型来装配注入,**@Qualifier**:可以改成名称@Resource:默认按照名称来装配注入,JDK的注解,新版本已经弃用@Autowired注解原理@Autowired的使用简化了我们的开发,实现 AutowiredAnnotationBeanPostProcessor 类,该类实现了 Spring 框架的一些扩展接口。
实现 BeanFactoryAware 接口使其内部持有了 BeanFactory(可轻松的获取需要依赖的的 Bean)。
实现 MergedBeanDefinitionPostProcessor 接口,实例化Bean 前获取到 里面的 @Autowired 信息并缓存下来;
实现 postProcessPropertyValues 接口, 实例化Bean 后从缓存取出注解信息,通过反射将依赖对象设置到 Bean 属性里面。
@SpringBootApplication@SpringBootConfiguration: 底层是Configuration注解,说白了就是支持JavaConfig的方式来进行配置
@EnableAutoConfiguration:开启自动配置功能
- @ComponentScan:就是扫描注解,默认是扫描当前类下的package
2、@SpringMVC
SpringMVC原理

客户端(浏览器)发送请求,直接请求到 DispatcherServlet 。
DispatcherServlet 根据请求信息调⽤ HandlerMapping ,解析请求对应的 Handler 。
解析到对应的 Handler (也就是 Controller 控制器)后,开始由HandlerAdapter 适配器处理。
HandlerAdapter 会根据 Handler 来调⽤真正的处理器开处理请求,并处理相应的业务逻辑。
处理器处理完业务后,会返回⼀个 ModelAndView 对象, Model 是返回的数据对象
ViewResolver 会根据逻辑 View 查找实际的 View 。
DispaterServlet 把返回的 Model 传给 View (视图渲染)。
- 把 View 返回给请求者(浏览器)
3、@SpringMybatis
简单的说就是#{}是经过预编译的,是安全的,**
Mybatis和Hibernate的区别
4、@Transactional
- MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
- NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
- NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
- SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
1、Spring中的设计模式
单例设计模式 : Spring 中的 Bean 默认都是单例的。需要最新大厂真题集的朋友可以评论“666”。

1万+

被折叠的 条评论
为什么被折叠?



