spring

spring

Posted by John Doe on 2021-07-18
Words 1.6k and Reading Time 6 Minutes
Viewed Times

SpringBean的生命周期

spirng根据类实例化对象后,对加了@Autowired、@Resource注解的属性进行赋值(属性填充)、进行对象初始化(@PostConstruct注解)、判断是否需要AOP(配置控制)需要的话AOP生成代理对象、代理对象注册成bean

spring 单例bean,bean按照type和name获取,spring有类似于map的结构存储bean,key为bean的name,value为bean,spring中该类似于map的容器叫单例缓存池。

获取流程 byType ——>根据Type从Spring容器里找到多个Bean———>查看bean是否(@autoWireCandidate = false过滤掉)————>是不是符合Qualifier(@Qualifier(”name”))分组——->取@Primary标注了的bean——->取优先级最高的Bean————>根据属性名字选出一个

@Autowire spring提供

bytype 再byName

@Resource java提供

byName找不到再 byType

Spring事务

开启事务相关注解:

@Configuration

@EnableTransactionManagement

@Transaction

Spring事务传播机制

spring事务传播的含义

简单的理解就是多个事务方法相互调用时,事务如何在这些方法间传播。默认是REQUIRED。

7种事务传播类型

按对当前事务的支持情况7种传播类型可分为三组

支持当前事务类型:

1 REQUIRED (必须有)

如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。

2 SUPPORTS (可有可无)

如果当前存在事务,则加⼊该事 务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。

3 MANDATORY (强制)

如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

不支持当前事务

4 REQUIRES_NEW

创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。

5 NOT_SUPPORTED

以⾮事务⽅式运⾏,如果 当前存在事务,则把当前事务挂起。

6 NEVER

以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。

其他

7 NESTED

如果当前存在事务,则创建⼀个事务 作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于 REQUIRED。即新创建事务。

事务传播机制demo示例

REQUIRED
1
2
3
4
5
6
7
8
9
10
11
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1); //调用A入参a1
testB(); //调用testB
}
@Transactional(propagation = Propagation.REQUIRED)
public void testB(){
B(b1); //调用B入参b1
throw RuntimeException; //发生异常抛出
B(b2); //调用B入参b2
}

由于testMain方法存在事务且调用testB方法,testB方法的事务会加入testMain的事务之中。testB抛出运行异常所以testMain方法和testB方法都会回滚。

1
2
3
4
5
6
7
8
9
10
public void testMain(){
A(a1); //调用A入参a1
testB(); //调用testB
}
@Transactional(propagation = Propagation.REQUIRED)
public void testB(){
B(b1); //调用B入参b1
throw RuntimeException; //发生异常抛出
B(b2); //调用B入参b2
}

由于testMain没有事务所以testB会新创建一个事务,testB方法发生回滚。

SUPPORTS
1
2
3
4
5
6
7
8
9
10
public void testMain(){
A(a1); //调用A入参a1
testB(); //调用testB
}
@Transactional(propagation = Propagation.SUPPORTS)
public void testB(){
B(b1); //调用B入参b1
throw RuntimeException; //发生异常抛出
B(b2); //调用B入参b2
}

由于testMain方法没有事务,testB将以非事务运行,B(b1)将执行,B(b2)不执行。

MANDATORY
1
2
3
4
5
6
7
8
9
10
public void testMain(){
A(a1); //调用A入参a1
testB(); //调用testB
}
@Transactional(propagation = Propagation.MANDATORY)
public void testB(){
B(b1); //调用B入参b1
throw RuntimeException; //发生异常抛出
B(b2); //调用B入参b2
}

testB方法将直接抛出异常,B(b1)方法不执行。

REQUIRES_NEW
1
2
3
4
5
6
7
8
9
10
11
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1); //调用A入参a1
testB(); //调用testB
throw RuntimeException; //发生异常抛出
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void testB(){
B(b1); //调用B入参b1
B(b2); //调用B入参b2
}

testMain方法发生回滚,testB方法成功执行。

NOT_SUPPORTED
1
2
3
4
5
6
7
8
9
10
11
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1); //调用A入参a1
testB(); //调用testB
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void testB(){
B(b1); //调用B入参b1
throw RuntimeException; //发生异常抛出
B(b2); //调用B入参b2
}

testB方法中没有事务,B(b1)方法成功执行。testMain方法回滚,A(a1)不执行。

NEVER
1
2
3
4
5
6
7
8
9
10
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1); //调用A入参a1
testB(); //调用testB
}
@Transactional(propagation = Propagation.NEVER)
public void testB(){
B(b1); //调用B入参b1
B(b2); //调用B入参b2
}

由于testMain方法存在事务,testB方法将抛出异常,testMain方法发生回滚所有方法都不执行。

NESTED

如果当前存在事务,则在嵌套事务(创建子事务)内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

  • 和REQUIRES_NEW的区别

REQUIRES_NEW是新建一个事务并且新开启的这个事务与原有事务无关,而NESTED则是当前存在事务时(我们把当前事务称之为父事务)会开启一个嵌套事务(称之为一个子事务)。
在NESTED情况下父事务回滚时,子事务也会回滚,而在REQUIRES_NEW情况下,原有事务回滚,不会影响新开启的事务。

  • 和REQUIRED的区别

REQUIRED情况下,调用方存在事务时,则被调用方和调用方使用同一事务,那么被调用方出现异常时,由于共用一个事务,所以无论调用方是否catch其异常,事务都会回滚
而在NESTED情况下,被调用方发生异常时,调用方可以catch其异常,这样只有子事务回滚,父事务不受影响

1
2
3
4
5
6
7
8
9
10
11
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1); //调用A入参a1
testB(); //调用testB
throw RuntimeException; //发生异常抛出
}
@Transactional(propagation = Propagation.NESTED)
public void testB(){
B(b1); //调用B入参b1
B(b2); //调用B入参b2
}

testMain方法和testB方法都不会执行,父事务回滚子事务也会发生回滚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1); //调用A入参a1
try{
testB(); //调用testB
}catch(Exception e){

}
A(a2);
}
@Transactional(propagation = Propagation.NESTED)
public void testB(){
B(b1); //调用B入参b1
throw RuntimeException; //发生异常抛出
B(b2); //调用B入参b2
}

testMain方法捕获了testB方法的异常,所以只有子事务发生回滚。

注意:虽然是2个事务,但由于方法a()抛出异常,test()方法内调用,相当于test方法内抛出了异常,所以事务回滚2个事务的方法都不执行。

该情况a()方法将执行,test()方法将回滚。

待续….


This is copyright.

...

...

00:00
00:00