Spring
1,Bean的生命周期
class ==> 实例化 ==> 对象 ==> 属性填充 ==> 初始化
2,AOP原理
class UserServiceProxy extends UserService{
private UserService target;
public void test(){
MyAspect.beforeMethod();
target.test();
}
}
3,单例Bean(线程不安全)
单例Bean 和 单例模式 不是同一种的
如果在类中声明成员变量,并且有读写操作(有状态)就是线程不安全
如果在方法中声明成员变量,并且有读写操作(无状态)就是线程安全
线程不安全解决:
1,添加 @Scope(“prototype”)
2,成员变量声明为 ThreadLocal
3,
构造方法中先根据 byType
来找,如果只找到一个就不找 byName
如果 byType
找到了多个,就继续根据byName
进行匹配,若没有就报错
private OrderService orderService;
public UserService(OrderService orderService) {
// 构造方法 这里是根据 bytype(OrderService) 在 byname(orderService) √
this.orderService = orderService;
}
public UserService(OrderService orderService1) { // 构造方法 这里是根据 bytype 在 byname √
this.orderService = orderService;
}
public UserService(OrderService orderService2) { // 构造方法 这里是根据 bytype 在 byname √
this.orderService = orderService;
}
public UserService(OrderService orderService3) {
// 构造方法 这里是根据 bytype 在 byname 这里得 orderService3 找不到 报错如下 ×
this.orderService = orderService;
}
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.yifan.spring.service.OrderService' available: expected single matching bean but found 3: orderService,orderService1,orderService2
==========================
// 一个单例bean orderService
@Component
public class OrderService {
}
public class AppConfig {
// 一个单例bean orderService1
@Bean
public OrderService orderService1(){
return new OrderService();
}
// 一个单例bean orderService2
@Bean
public OrderService orderService2(){
return new OrderService();
}
}
==========================
OrderService orderService = context.getBean("orderService", OrderService.class);
OrderService orderService1 = context.getBean("orderService1", OrderService.class);
OrderService orderService2 = context.getBean("orderService2", OrderService.class);
// 3个不同bean
System.out.println(orderService); // com.yifan.spring.service.OrderService@932bc4a
System.out.println(orderService1); // com.yifan.spring.service.OrderService@d29f28
System.out.println(orderService2); // com.yifan.spring.service.OrderService@2fd1433e
4,@Autowired
这个是spring实现得
Autowired 根据
byType
,byName
进行匹配byType 和 byName 之间还有很多过滤条件 一般用@Autowired
就是先 byType
在 byName
5,@Resources
这个注解是java实现得
如果 @Resources 中写了name 属性,那么就根据 byName 进行匹配,找不到就报错
如果没写name,那么就先判断单例池中有没有这个属性名字得单例bean,如果有就把这个值给拿出来赋值
如果没有也不报错,最后在根据byType查找
就是先 byName
在 byType
6,@Transactional
在同一类中,在没加事务注解的方法中调用加了事务注解的方法,不执行事务
7,Spring Event
事件通知机制,
默认情况下,Spring是同步执行Event的响应方法,
若需要异步处理则可在监听方法上添加注解 @Async 即可,别忘了开启@EnableAsync
- 我们可以在单一方法内Publish多个事件,互不干扰
- 监听者可以基于表达式进行基本的过滤
- 一个事件可以被重复监听
8,延迟加载,懒加载
- 使用注解:
@Lazy
- 效果:Spring容器在启动时会创建所有的Bean对象,使用@Lazy注解可以将Bean对象的创建延迟到第一次使用Bean的时候
9,分布式事务
mysql事务
事务的4个条件
- 原子性Atomicity, A
- 一致性Consistency, C
- 隔离性Isolation, I
- 持久性Durability, D
事务的隔离级别
- 读未提交
- 读已提交
- 可重复读(默认隔离级别)
- 串行化
begin; # 开始事务
insert into user values(name,age);
commit; # 提交事务
- BEGIN 开始一个事务
- ROLLBACK 事务回滚
- COMMIT 事务确认
Spring事务
Spring Boot中实现事务没有额外的Jar包,还是基本的数据库访问包,比如
mybatis
注解事务@Transactional
@Service
public class PersonService {
@Resource
private PersonMapper personMapper;
@Resource
private CompanyMapper companyMapper;
@Transactional(rollbackFor = {RuntimeException.class, Error.class},propagation = Propagation.REQUIRED)
public void saveOne(Person person) {
Company company = new Company();
company.setName("tenmao:" + person.getName());
companyMapper.insertOne(company);
personMapper.insertOne(person);
}
}
注解属性
rollbackFor
:触发回滚的异常,默认是RuntimeException
和Error
isolation
: 事务的隔离级别,默认是Isolation.DEFAULT
也就是数据库自身的默认隔离级别,比如MySQL是ISOLATION_REPEATABLE_READ
可重复读
propagation 传播级别
传播行为 | 意义 |
---|---|
PROPAGATION_MANDATORY | 表示该方法必须运行在一个事务中。如果当前没有事务正在发生,将抛出一个异常 |
PROPAGATION_NESTED | 表示如果当前正有一个事务在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于封装事务进行提交或回滚。如果封装事务不存在,行为就像PROPAGATION_REQUIRES一样。 |
PROPAGATION_NEVER | 表示当前的方法不应该在一个事务中运行。如果一个事务正在进行,则会抛出一个异常。 |
PROPAGATION_NOT_SUPPORTED | 表示该方法不应该在一个事务中运行。如果一个现有事务正在进行中,它将在该方法的运行期间被挂起。 |
PROPAGATION_SUPPORTS | 表示当前方法不需要事务性上下文,但是如果有一个事务已经在运行的话,它也可以在这个事务里运行。 |
PROPAGATION_REQUIRES_NEW | 表示当前方法必须在它自己的事务里运行。一个新的事务将被启动,而且如果有一个现有事务在运行的话,则将在这个方法运行期间被挂起。 |
PROPAGATION_REQUIRES | 表示当前方法必须在一个事务中运行。如果一个现有事务正在进行中,该方法将在那个事务中运行,否则就要开始一个新事务。默认事务 |
案例
ServiceA {
void methodA() {
ServiceB.methodB();
}
}
ServiceB {
void methodB() {
}
}
假如当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候
1、如果ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA的事务内部,就不再起新的事务。这时只有外部事务并且他们是共用的,所以这时ServiceA.methodA或者ServiceB.methodB无论哪个发生异常methodA和methodB作为一个整体都将一起回滚。
2、如果ServiceA.methodA没有事务,ServiceB.methodB就会为自己分配一个事务。这样,在ServiceA.methodA中是没有事务控制的。只是在ServiceB.methodB内的任何地方出现异常,ServiceB.methodB将会被回滚,不会引起ServiceA.methodA的回滚
日夜颠倒头发少 ,单纯好骗恋爱脑 ,会背九九乘法表 ,下雨只会往家跑 ,搭讪只会说你好 ---- 2050781802@qq.com