Spring

Spring

1,Bean的生命周期

class ==> 实例化 ==> 对象 ==> 属性填充 ==> 初始化

image-20210423152922300

2,AOP原理

class UserServiceProxy extends UserService{

    private UserService target;
    public void test(){
        MyAspect.beforeMethod();
        target.test();
    }

}

3,单例Bean(线程不安全)

单例Bean 和 单例模式 不是同一种的

如果在类中声明成员变量,并且有读写操作(有状态)就是线程不安全

如果在方法中声明成员变量,并且有读写操作(无状态)就是线程安全

线程不安全解决:

1,添加 @Scope(“prototype”)

2,成员变量声明为 ThreadLocal

image-20230202141020698

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

就是先 byTypebyName

5,@Resources

这个注解是java实现得

如果 @Resources 中写了name 属性,那么就根据 byName 进行匹配,找不到就报错

如果没写name,那么就先判断单例池中有没有这个属性名字得单例bean,如果有就把这个值给拿出来赋值

如果没有也不报错,最后在根据byType查找

就是先 byNamebyType

6,@Transactional

在同一类中,在没加事务注解的方法中调用加了事务注解的方法,不执行事务

7,Spring Event

事件通知机制,

默认情况下,Spring是同步执行Event的响应方法,

若需要异步处理则可在监听方法上添加注解 @Async 即可,别忘了开启@EnableAsync

  1. 我们可以在单一方法内Publish多个事件,互不干扰
  2. 监听者可以基于表达式进行基本的过滤
  3. 一个事件可以被重复监听

image-20210726105343141

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:触发回滚的异常,默认是RuntimeExceptionError

  • 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

×

喜欢就点赞,疼爱就打赏

相册 说点什么