SpringBoot和Spring的关系
好的我下面从两个方面来回答SpringBoot和Spring的区别
- 首先就是依赖管理
Spring需要需要手动生命每个依赖的版本,并且需要确保各个组件版本之间的兼容性。而SpringBoot通过starter依赖自动管理版本。
<!--SpringBoot 引入MyBatis starter,自动整合MyBatis与Spring -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version> <!-- 仅需指定starter版本,内部依赖由其管理 -->
</dependency>
<!--Spring 引入第三方框架(如MyBatis)需手动添加依赖及版本 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version> <!-- 需与MyBatis和Spring版本兼容 -->
</dependency>
- Bean与第三方的整合 Spring需要手动定义基础的Bean(DataSource,SqlSessionFactory)并配置整合第三方框架的细节 SpringBoot通过自动配置类(AutoConfiguration)默认创建常用的Bean,仅需在application.yml中配置参数即可。
// Spring传统项目的核心配置类
@Configuration
// 需手动开启组件扫描,指定扫描路径
@ComponentScan(basePackages = "com.example.service")
// 需手动开启MVC注解驱动
@EnableWebMvc
public class SpringConfig {
// 需手动定义DispatcherServlet(SpringMVC核心)
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
// 需手动注册DispatcherServlet到Servlet容器
@Bean
public ServletRegistrationBean<DispatcherServlet> dispatcherServletRegistration() {
ServletRegistrationBean<DispatcherServlet> registration = new ServletRegistrationBean<>(
dispatcherServlet(), "/");
registration.setLoadOnStartup(1);
return registration;
}
// 需手动定义数据源
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
// 需手动定义MyBatis的SqlSessionFactory
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
// 需手动指定Mapper位置
sessionFactory.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return sessionFactory.getObject();
}
}
// SpringBoot项目的核心启动类(一键开启所有核心功能)
@SpringBootApplication
// 无需手动@ComponentScan(默认扫描当前包及子包)
// 无需手动@EnableWebMvc(web starter自动开启)
public class SpringBootDemoApplication {
// 主方法直接启动嵌入式服务器
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
// 大部分配置无需手动定义,仅需在application.yml中配置参数
// 如需自定义Bean,直接定义即可(自动被Spring容器管理)
@Bean
public UserService userService() {
return new UserService();
}
}
Spring的三级缓存是什么,如何通过三级缓存解决循环依赖
一个新对象在创建的过程中要先去缓存中查询,依次查询一级缓存、二级缓存、三级缓存,如果都没有查到,那么就通过反射创建出这个新对象,之后包装为ObjectFactory类型放在三级缓存中。下一步就是填充A对象的属性,如果A对象的属性有一个是B对象,那么找到B对象的过程也是以依次进行三级查询,如果查不到B就使用反射创建B,然后包装为ObjectFactory类型放入三级缓存中,之后进行B对象的属性填充,发现B对象的属性有一个是A,然后依次查询A在三级缓存中是否存在,这一次发现A存在于第三级缓存中。
然后使用ObjectFactory类型的getObject获取真正的的对象A,并将这个A放入到二级缓存中,然后删除三级缓存中的A对象的ObjectFactory,这样就完成了B对象的属性填充工作,之后会进行初始化使用@PostConstruct注解。之后会进行缓存转移,从三级缓存中移除B,然后在一级缓存中加入B。
之后继续进入到A对象的初始化和缓存转移。
放入二级缓存之后再进行初始化。
二级缓存可能存放的可能是原对象也可能是代理对象
生成代理的时期:如果没有循环依赖,代理在Bean初始化之后生成;如果出现循环依赖代理在初始化之前生成