Spring底层源码分析

spring依赖注入底层原理解析

spring之bean对象生命周期步骤详情
在这里插入图片描述

流程:

UserService.class —>推断构造方法—>普通对象----依赖注入------>初始化(afterPropertiesSet方法)------>初始化后(AOP)------>代理对象----->放入Map<baenName,Bean对象>

推断构造方法
@Component
public class UserService implements InitializingBean {@Autowiredprivate OrderService orderService;//无参构造方法public UserService() {System.out.println(8);}//有参构造方法public UserService(OrderService orderService) {this.orderService = orderService;System.out.println(1);}//有参构造方法public UserService(OrderService orderService, OrderService orderServicel) {this.orderService = orderService;System.out.println(2);}
}

以上如何选择呢?
spring会默认使用无参构造方法,如果没有无参的有多个有参的构造方法spring就会报错
在这里插入图片描述
如果有多个就可以明确给spring指定哪一个构造方法-------在构造方法上加@Autowired 注解
在这里插入图片描述

依赖注入

在这里插入图片描述
判断普通对象中是否有Autowired注解再进行依赖注入
源码大体逻辑:
在这里插入图片描述
依赖注入的话如何判断注入对象就是想要的依赖对象呢?

先byType---->再byName 在 Map<beaName,Bean对象> 中寻找

在这里插入图片描述
spring中使用 对象类型 和 对象名字进行识别唯一的

类型可以一样 名字必须不一样
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在Bean中的地址不一样生成的Bean不同

初始化

初始化必须实现spring提供的指定方法

import org.springframewolk.beans.factory.InitializingBean;//实现一个接口
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class UserService implements InitializingBean {@Autowiredprivate OrderService orderService;//初始化执行自己定义@Overridepublic void afterPropertiesSet() throws Exception {System.out.println(orderService);}public void test() {System.out.println(orderService);}
}

源码中判断UserService是否实现了InitializingBean接口,如果实现了就调用afterPropertiesSet自己定义初始化方法
在这里插入图片描述

AOP

UserServiceProxy对象===UserService代理对象----->UserService代理对象.target


UserService代理对象.test()
class UserServiceProxy extends UserService {UserService target;public void test(){// 切面逻辑// target.test()  //UserService普通对象.test()
}
放入Map<baenName,Bean对象>

放入Bean对象到Map<String,Object>的API(自己调用方法),一般是再UserService.class方法上面加Component注解,加入到Map<String,Object>的

//放入Bean对象到Map<String,Object>的API
Object o = new Object();|I
applicationContext.getBeanFactory().registerSingleton( beanName: "xxx",o);

放入Map<String,Object>的源码
在这里插入图片描述

spring事务

流程:

Spring事务切面逻辑----->@Transactional开启Spring事务----->利用事务管理器新建一个数据库连接conn ThreadLocal------>conn.autocommit=false------>target.test() //UserService普通对象.test() jdbcTemplate 执行sql1.sql2 ----->conn.rollback()conn.commit()

1、@Transactional
2、开启Spring事务
3、利用事务管理器新建一个数据库连接conn ThreadLocal
4、conn.autocommit=false
5、target.test() // UserService普通对象.test() jdbcTemplate执行sql1.sql2
6、conn.rollback()conn.commit()

准备Bean对象

配置事务创建链接数据库的对象Bean相当于mybatis对象

@ComponentScan("com.zhouyu")
@EnableTransactionManagement  //用于启用基于注解的事务管理
@Configuration //通过配置类可以定义和组装Spring Bean。  返回的是同一个dataSource对象 AppConfig代理对象
public class AppConfig {@Bean
public JdbcTemplate jdbcTemplate() {return new JdbcTemplate(dataSource());
}//利用事务管理器创建数据库链接
@Bean
public PlatformTransactionManager transactionManager() {DataSourceTransactionManager transactionManager = newDataSourceTransactionManager();transactionManager.setDataSource(dataSource());return transactionManager:
}@Bean
public DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.seturl("jdbc :mysql://127.0.0.1:3306/tuling");dataSource.setUsername("root");dataSource.setPassword("Zhouyu123456***");returm dataSource;
}

@EnableTransactionManagement 是Spring框架提供的一个注解,用于启用基于注解的事务管理。通过使用这个注解,你可以开启Spring对事务的自动管理功能,使得你可以在方法上使用 @Transactional 注解来声明事务。

@EnableTransactionManagement 主要有以下两个属性:

  • mode(默认为 AdviceMode.PROXY):指定事务代理的模式。可以选择的值有 AdviceMode.PROXY 和
    AdviceMode.ASPECTJ。默认是 AdviceMode.PROXY,表示使用基于代理的方式实现事务管理。如果选择
    AdviceMode.ASPECTJ,表示使用基于AspectJ的方式实现事务管理。
  • proxyTargetClass(默认为 false):用于确定代理是否应该使用目标类的类代理,而不是目标类实现的接口。如果设置为
    true,代理将使用目标类的类代理(CGLIB代理),如果设置为 false,代理将使用目标类实现的接口代理(JDK动态代理)。

当你在配置类上使用 @EnableTransactionManagement 注解时,Spring框架会自动扫描带有 @Transactional 注解的方法,并在这些方法周围织入事务管理的逻辑。如果一个带有 @Transactional 注解的方法执行过程中出现了异常,Spring会自动回滚事务。这个注解的作用是简化事务管理的配置和使用,提高开发效率。

测试事务
class UserService{@Autowiredprivate JdbcTemplate jdbcTemplate;@Transactionalpublic void test() {jdbcTemplate.execute( sql: "insert into t1 values(1,1,1,1,'1')");//抛空指针异常,触发事务回滚throw new NullPointerException();}	
}
主程序逻辑

在这里插入图片描述
检查数据库中数据是否插入成功

事务失效

1、原因:

一个对象调用了另一个对象
代理对象和普通对象是两个对象

class UserService{@Autowiredprivate JdbcTemplate jdbcTemplate;@Transactionalpublic void test() {jdbcTemplate.execute( sql: "insert into t1 values(1,1,1,1,'1')");throw new NullPointerException();a();}//多个事务报错propagation = Propagation.NEVER@Transactional(propagation = Propagation.NEVER)public void a(){jdbcTemplate.execute( sql: "insert into t1 values(2,2,2,2, '2' )");}
}

以上原因一个对象调用了另一个对象的a()
使用this.a()不能解决,因为this是普通对象

解决方法:

1、新建一个Base类,把需要调用的功能拿到另一个Bean对象中
在这里插入图片描述
新建类UserServiceBase,把UserService的a方法删掉,不要有相同的方法
在这里插入图片描述

2、自己注入自己
在这里插入图片描述

1、原因:

在这里插入图片描述

@ComponentScan("com.zhouyu")
@EnableTransactionManagement  //用于启用基于注解的事务管理
@Configuration //AppConfig代理对象来掉用
public class AppConfig {@Beanpublic JdbcTemplate jdbcTemplate() {return new JdbcTemplate(dataSource());}//利用事务管理器创建数据库链接@Beanpublic PlatformTransactionManager transactionManager() {DataSourceTransactionManager transactionManager = newDataSourceTransactionManager();transactionManager.setDataSource(dataSource());return transactionManager:}//创造dataSource对象@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.seturl("jdbc :mysql://127.0.0.1:3306/tuling");dataSource.setUsername("root");dataSource.setPassword("Zhouyu123456***");returm dataSource;}
}

@Configuration 中使用的是super.方法

AOP中使用的是target.方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/502064.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软考-计算题

1.二维矩阵转换成一维矩阵 2.算术表达式&#xff1a; 3.计算完成项目的最少时间&#xff1a;之前和的max&#xff08;必须之前的所有环节都完成&#xff09; 松弛时间&#xff1a;最晚开始时间-最早开始时间 最早&#xff1a;之前环节都完成的和的max 最晚&#xff1a;总时间…

word文档空格不能有下划线【笔记】

word文档空格不能有下划线 2024-3-1 21:20:24 推荐 word下划线打不出来了&#xff0c;是怎么回事&#xff1f; 问题 字后面打不出来下划线 操作 1.点击文件 左上角&#xff0c;点击“文件”。 2.点击选项 鼠标下滑&#xff0c;点击“选项”。 3.点击常规与保存 点击“…

吸引用户购买产品的文案技巧,媒介盒子揭秘

在营销过程中&#xff0c;想要吸引用户购买产品&#xff0c;文案是重中之重&#xff0c;需要一定的技巧才能将文案写好&#xff0c;今天媒介盒子就来和大家聊聊&#xff1a;在品牌推广中如何通过一些小技巧吸引用户购买产品&#xff1a; 一、 少说专业术语 少说行话、黑话。多…

PyQt5嵌入外部exe(如微信、cmd窗口)

背景&#xff1a; PyQt在使用中需要使用一下另外一个exe程序&#xff0c;需要嵌入一下 过程&#xff1a; Qt实战11.进程窗口集成之假装写了个第三方软件 - Qt小罗 - 博客园 (cnblogs.com) python操作windows窗口获取正在运行的窗口句柄_python使用句柄操作-CSDN博客 翻译成…

类加载的基本流程

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;JavaEE &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 类加载 1. 加载2. 验证3. 准备4. 解析5. 初…

防御保护课程笔记

内容安全 防病毒 过滤技术 密码学

ChatGPT学习第四周

&#x1f4d6; 学习目标 ChatGPT实践操作 通过实际操作和练习&#xff0c;加深对ChatGPT功能的理解。 项目&#xff1a;创建一个ChatGPT应用案例 设计一个基于ChatGPT的小项目&#xff0c;将理论应用于实践。 ✍️ 学习活动 学习资料 《万字干货&#xff01;ChatGPT 从零完…

【计算机网络】五种IO模型与IO多路转接之select

文章目录 一、五种IO模型二、非阻塞IO1.fcntl2.实现函数SetNoBlock3.轮询方式读取标准输入 三、I/O多路转接之select1.初识select2.select函数原型3.socket就绪条件4.select的特点5.select缺点6.select使用案例--只读取数据的server服务器1.err.hpp2.log.hpp3.sock.hpp4.select…

动态规划课堂3-----简单多状态问题(买卖股票最佳时机)

目录 引入&#xff1a; 例题1&#xff1a;按摩师&#xff08;打家劫舍I&#xff09; 例题2&#xff1a;打家劫舍II 例题3&#xff1a;删除并获得点数 例题4&#xff1a;粉刷房子 例题5&#xff1a;买卖股票的最佳时机含冷冻 结语&#xff1a; 引入&#xff1a; 相信看到…

使用MyBatisPlus实现向数据库中存储List类型的数据

使用MyBatisPlus实现向数据库中存储List类型的数据 问题描述 建表时&#xff0c;表中的这五个字段为json类型 但是在入库的时候既不能写入数据&#xff0c;也不能查询出数据。 解决方案&#xff1a; 1.首先明确&#xff0c;数据存入的时候是经过了数据类型转化&#xff0c…

软件测试——性能测试

目录 一、性能测试简介 二、性能测试指标 三、性能测试的流程 四、Jmeter简介 五、Jmeter常见测试框架 六、Jmeter录制脚本 七、脚本增强 八、Jmeter脚本参数化 九、断言 十、关联 十一、JDBC请求 十二、分布式测试 十三、性能测试报告 一、性能测试简介…

VSCode上搭建C/C++开发环境(vscode配置c/c++环境)Windows系统---保姆级教程

引言劝退 VSCode&#xff0c;全称为Visual Studio Code&#xff0c;是由微软开发的一款轻量级&#xff0c;跨平台的代码编辑器。大家能来搜用VSCode配置c/c&#xff0c;想必也知道VSCode的强大&#xff0c;可以手握一个VSCode同时编写如C&#xff0c;C&#xff0c;C#&#xff…