spring源码核心

spring创建bean的生命周期(大概)

容器

可以理解容器为一个Map
spring源码核心_第1张图片

通过类的构造方法创建对象

有两个有参构造方法,就坏了,spring不知道用哪个,这个时候可以加**@Autowired**
有无参和有参时,选无参
只有一个构造方法就用它
spring源码核心_第2张图片
比如有两个有参构造:
spring源码核心_第3张图片

比如如果只有一个有参构造,
spring源码核心_第4张图片
此时传入的orderService有值吗?如果它是一个bean,就有值否则报错
先根据入参类型去找spring容器map里找如果找到一个直接用,但是可能找到多个对象,下面就有三个对象了
spring源码核心_第5张图片
spring源码核心_第6张图片
所以再通过入参名字去找唯一的一个

依赖注入

依赖注入原理伪代码:
spring源码核心_第7张图片
注入的值还是从容器map里找
后续过程:
在这里插入图片描述

初始化前

如果想要在成为bean对象之前满足从数据库读信息到属性里(即属性赋值需要的数据库的值,可以加注解:
在这里插入图片描述
spring源码核心_第8张图片
所以此时就是去找哪些方法加了postconstruct注解
spring源码核心_第9张图片

初始化

初始化判断当前对象是否实现InitializingBean接口,重写afterPropertiesSet方法
在这里插入图片描述
如何判断?instance of InitializingBean
spring源码核心_第10张图片

初始化后

处理对象方法里有aop的方法,并产生代理对象,代理对象成为bean
在这里插入图片描述

全部流程

在这里插入图片描述

AOP

增加切面AspectJ包,并在Config类上添加允许被切面的注解**@EnableAspectJAutoProxy**
spring源码核心_第11张图片
spring源码核心_第12张图片

AOP在初始化后阶段,利用CGLIB包生成代理对象。CGLIB是一个反射的包,和JDK的反射不同,cglib反射的对象可以不用实现接口,直接继承要被代理的类。
spring通过cglib的代理类创建代理对象,然后将原来的对象(拥有依赖注入的对象)赋给代理类里的target属性,代理对象调用的不再是父类对象的方法而是target对象的方法,同时执行切面方法。
所以绕了一圈除了多了切面,依赖注入的属性值和方法都是原来的那个对象
spring源码核心_第13张图片

那如何确定该对象被切面了呢?

切面也是bean

  1. 首先在容器里找出所有的切面bean
  2. 遍历每一个切面bean
  3. 遍历其切面方法查看是否添加了通知注解@Before,@After…
  4. 通过方法的注解查看是否切点是哪个类的方法,缓存map
  5. 在代理对象的方法中织入切面,从4中的map缓存中取

spring 事务

在config配置类添加允许事务管理注解
spring源码核心_第14张图片

加了注解**@Transactional**,抛出异常会回滚
spring源码核心_第15张图片
事务也是基于AOP实现的,也是动态代理对象去执行,一般事务的AOP的order最小也就是优先级最低,应该先执行其他自定义的AOP切面

  1. 首先判断方法是否被transactional注解修饰
  2. 由事务管理器创建数据库连接conn
  3. 设置conn.autocommit = false
  4. 执行原方法
  5. 根据
    spring源码核心_第16张图片

事务失效

propagation.never模式下,不允许有已经存在的事务,否则会抛出异常
首先调用userservice.test()时是代理对象调用test,开启事务,然后用target.test调用,因此数据库insert操作开始就是原来的普通对象target在执行,因此a方法是target调用,所以添加的事务没有用(必须是代理对象才有切面才能开启事务一系列的操作),此时事务失效,不会抛出异常。
spring源码核心_第17张图片
怎么修改呢
可以实现自己注入自己。因为有transactional修饰,所以注入的是代理对象,此时a方法的调用也是代理对象,此时会抛出异常。
spring源码核心_第18张图片

@Configuration

config类中如果不添加该注解,则事务管理器连接的数据库和JDBCTemplate连接的数据库是两个,所以事务失效。
spring源码核心_第19张图片
添加了该注解,jdbc会拿到和事务管理器的同一个数据库,和代理模式有关:config类也是一个bean,利用的是他的代理对象,逻辑是连接数据库时会检查是否已经有了连接池DataSource bean,如果有直接返回,不用新建。

你可能感兴趣的:(Java后端技术,spring,java)