Spring Boot、Spring MVC 和 Spring 有什么区别?
- SpringBoot是对Spring和SpringMVC的整合,把之前繁琐的配置变成了自动装配
自动装配原理
- 再启动类上的注解叫@SpringBootApplication,这个注解里面有包含了一个@EnableAutoConfiguration注解,这个注解就是实现自动装配的入口
- 在这个注解里面,有一个@Import注解,里面配置了一个实现类AutoConfigurationImportSelector,这个类正是去加载配置的核心类,其中getCandidateConfigurations()方法里面去加载了spring.factories文件
- 通过该文件就可以找到配置的所有要自动装配的类了,这里面的类很多,但最后都会过滤掉很多,最终剩下当前环境需要使用的。
SpringBoot 解决循环依赖——三级缓存
- 如果是多例模式就直接抛出异常
对于单例模式
在DefaultSingletonBeanRegistry类内部维护了三个Map即三级缓存
- singletonObjects “单例池”“容器”
- singletonFactories 映射创建Bean的原始工厂
earlySingletonObjects 映射Bean的早期引用,不完整的bean
protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {synchronized(this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;}
实例化 A,此时 A 还未完成属性填充和初始化方法(@PostConstruct)的执行,A 只是一个半成品。
- 为 A 创建一个 Bean 工厂,并放入到 singletonFactories 中。
- 发现 A 需要注入 B 对象,但是一级、二级、三级缓存均为发现对象 B。
- 实例化 B,此时 B 还未完成属性填充和初始化方法(@PostConstruct)的执行,B 只是一个半成品。
- 为 B 创建一个 Bean 工厂,并放入到 singletonFactories 中。
- 发现 B 需要注入 A 对象,此时在一级、二级未发现对象 A,但是在三级缓存中发现了对象 A,从三级缓存中得到对象 A,并将对象 A 放入二级缓存中,同时删除三级缓存中的对象 A。(注意,此时的 A 还是一个半成品,并没有完成属性填充和执行初始化方法)
- 将对象 A 注入到对象 B 中。
- 对象 B 完成属性填充,执行初始化方法,并放入到一级缓存中,同时删除二级缓存中的对象 B。(此时对象 B 已经是一个成品)
- 对象 A 得到对象 B,将对象 B 注入到对象 A 中。(对象 A 得到的是一个完整的对象 B)
- 对象 A 完成属性填充,执行初始化方法,并放入到一级缓存中,同时删除二级缓存中的对象 A。
@Autowired注解和@Resource的区别
- @Autowired 由Spring提供,通过type来注入Bean,如果没有就报错
- @Resource 由J2EE提供,默认先通过name去匹配Bean,没有找到再通过type去注入Bean
过滤器、拦截器的区别,执行顺序是怎么样的?
- 实现方式不同:过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。
- 使用范围不同:过滤器是servlet包下的,所以它依赖Tomcat,所以只能在Web程序里使用,而拦截器是Spring提供的,所以只要引入Spring就可以使用
- 执行顺序:过滤器在拦截器的外层
Bean 生命周期
- Bean创建前的准备阶段
- Bean容器在配置文件中找到Spring Bean的定义以及相关的配置
- 实例化回调相关的后置处理器如BeanFactoryPostProcessor、BeanPostProcessor、InstantiationAwareBeanPostProcessor等
- 创建Bean的实例
- Srping 容器使用Java反射API创建Bean的实例
- 扫描Bean声明的属性并解析
- 开始依赖注入
- 开始依赖注入,解析所有需要赋值的属性并赋值
- 如果Bean类实现BeanNameAware接口,则将通过传递Bean的名称来调用setBeanName()方法
- 如果Bean类实现BeanFactoryAware接口,则将通过传递BeanFactory对象的实例来调用setBeanFactory()方法
- 如果有任何与BeanFactory关联的BeanPostProcessors对象已加载Bean,则将在设置Bean属性之前调用postProcessBeforeInitialization()方法
- 如果Bean类实现了InitializingBean接口,则在设置了配置文件中定义的所有Bean属性后,将调用afterPropertiesSet()方法。
- 缓存到Spring容器
- 销毁Bean的实例
