Spring
Day11:Spring
目标
1 | Spring |
Bean 生命周期
1 | 1. 实例化(调用构造方法) |
AOP
AOP(面向切面编程)就是把日志、事务、权限等横切关注点从业务代码中抽离出来,统一增强目标方法。
1. 为什么Spring要IOC为什么比new好?
第一,降低耦合。对象不再依赖具体实现,而是依赖 Spring 容器管理。
第二,统一管理生命周期。Spring 可以统一管理 Bean 的创建、销毁、作用域(Singleton、Prototype 等)。
第三,方便扩展。例如以后 UserDao 换实现,或者增加代理、事务,都不用修改业务代码。
2. Bean生命周期五步是什么?
创建bean、注入依赖、初始化、使用、销毁
3. 为什么@PostConstruct里面@Autowired已经可以使用?
PostConstruct是在初始化之前,注入依赖之后。所以已经可以使用依赖的对象了。
构造方法里面不能保证@Autowired已经完成但是@PostConstruct一定可以。
4. 为什么AOP适合日志事务权限。为什么不适合业务?
aop适合通用的代码逻辑。具体的业务情况谁和谁都不一样。
5. 你的GIS平台如果不用AOP日志怎么写?用了AOP有什么好处?
如果不用aop就只能每个方法都手写一遍记录日志的代码。使用了aop后只需要写一次。
6. 为什么Spring默认Bean是Singleton为什么不是Prototype?
绝大部分 Bean 都是无状态的,比如service、dao,多个线程共享一个实例没有问题。
创建对象、GC会消耗性能,对象越多越占内存。
只有少数需要保存状态的对象才适合 Prototype。比如dto、entity。
7. 为什么SpringIOC底层大量使用反射为什么不用new UserService()
因为springIOC是在运行时创建的bean,Spring 在编译时根本不知道有哪些 Bean。
用new的话,要求编译时就知道类型。
8. 为什么@Autowired默认按类型(Type)注入而不是按名字(Name)?
原因一:面向接口编程
@Autowired可以注入接口或者抽象类。如果实现类只有一个,spring会把这个实现类注入进来。如果需要按名字注入可以用@Resource或者@Qualifier
原因二:名字容易变
@Autowired 默认按类型注入,是为了支持面向接口编程,降低实现类变更带来的影响。
9. 为什么Spring有时候可以解决循环依赖有时候又不能?
1 |
|
流程:
1 | 创建A |
Spring 能解决的是 Singleton Bean 的属性注入循环依赖。
那什么时候解决不了?
第一种:构造器注入
对象都创建不了
第二种:Prototype
每次都是new,没有三级缓存
Spring 能解决 Singleton Bean 的属性注入循环依赖,因为 Bean 实例化后会提前暴露到三级缓存,后续 Bean 可以先引用这个未完全初始化的对象;而构造器注入和 Prototype Bean 不支持这种机制,因此无法解决循环依赖。
Day12:事务
ACID
Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)
事务保证一组操作具有 ACID 特性,要么全部成功,要么全部失败。
1. 为什么Spring事务使用AOP为什么不用每个方法自己写commit?
事务属于横切逻辑。Spring利用aop已经完成了事务开启和事务提交回滚的通用代码。
事务属于横切关注点,每个业务方法都可能需要事务,因此 Spring 使用 AOP 将事务逻辑统一织入目标方法,避免每个方法重复编写 begin、commit、rollback 等代码。
2. 为什么自己调用this.save()事务失效?
因为 Spring 的事务是通过代理对象实现的。外部调用的是代理对象,所以事务能够生效;而 this.save() 是对象内部调用,没有经过代理对象,而是直接调用目标对象的方法,因此事务拦截器不会执行。
3. 为什么private 方法@Transactional失效?
JDK 动态代理是代理接口,接口里没有private方法。CGLIB代理的是子类,子类不能重写private方法。
private 方法不能被代理对象重写,因此事务增强无法织入。
4. REQUIRED和REQUIRES_NEW区别什么时候用REQUIRES_NEW?
REQUIRED是如果有事务就加入事务。没有就创建一个事务。
REQUIRES_NEW 会挂起当前事务,然后创建一个新事物。
当需要两个不同事物的情况下使用REQUIRES_NEW,比如业务代码和保存日志需要是两个事务,业务代码异常回滚,日志应该要保存下来。
流程:
1 | A事务 |
5. 为什么Spring 默认只回滚 RuntimeException?为什么throw new IOException();事务默认不回滚?
非RuntimeException需要手动处理,spring就认为开发者已经知道这个异常,应该主动处理。RuntimeException可能是程序出现bug应该回滚。
Spring 默认认为 Checked Exception(受检异常)是开发者可以预期并处理的业务异常,因此默认不回滚;而 RuntimeException 通常表示程序发生了不可预期的错误,因此默认回滚事务。
6. 为什么下面代码事务最后提交了?
1 |
|
因为方法最终没有抛出RuntimeException。
Day13:Spring Boot
1. Spring Boot 和 Spring 有什么区别?
springboot基于spring,由于spring需要大量繁琐的配置,springboot简化了这一流程。他的约定大于配置。会根据依赖自动加载需要的bean。
Spring Boot 是 Spring 的快速开发框架。
2. @SpringBootApplication 为什么只要一个注解?它里面最重要的三个注解是什么?各自负责什么?
@SpringbootConfigurarion
标注配置启动类
@EnableAutoConfiguration
开启自动配置,根据依赖自动配置。
@ComponentScan
开启注解扫描。例如@Configuration @Componet @Service
3. 为什么导入:spring-boot-starter-data-redis RedisTemplate 就自动有了?
因为这个依赖里面有自动装配RedisTemplate的配置类。
4. 为什么Spring Boot不会把所有AutoConfiguration全部加载?
他会根据条件,比如@ConditionalOnClass、@ConditionalOnMissingBean等。
Spring Boot 会根据各种条件注解(如 @ConditionalOnClass、@ConditionalOnMissingBean 等)决定是否加载自动配置,而不是无条件全部加载。
5. 为什么spring-boot-starter-web叫Starter为什么不是spring-web?
Starter就是依赖管理。自动引入需要的全部依赖,本质就是依赖聚合。











