Spring底层源码分析

news2024/11/20 9:33:31

spring依赖注入底层原理解析

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

流程:

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

推断构造方法
@Component
public class UserService implements InitializingBean {
	@Autowired
	private 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 {
	@Autowired
	private OrderService orderService;
	
	//初始化执行自己定义
	@Override
	public 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{

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@Transactional
	public void test() {
		jdbcTemplate.execute( sql: "insert into t1 values(1,1,1,1,'1')");
		//抛空指针异常,触发事务回滚
		throw new NullPointerException();

	}	
}
主程序逻辑

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

事务失效

1、原因:

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

class UserService{

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	@Transactional
	public 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 {
	@Bean
	public JdbcTemplate jdbcTemplate() {
		return new JdbcTemplate(dataSource());
	}
	
	//利用事务管理器创建数据库链接
	@Bean
	public PlatformTransactionManager transactionManager() {
		DataSourceTransactionManager transactionManager = newDataSourceTransactionManager();
		transactionManager.setDataSource(dataSource());
		return transactionManager:
	}
	
	//创造dataSource对象
	@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;
	}
}

@Configuration 中使用的是super.方法

AOP中使用的是target.方法

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WEB漏洞 逻辑越权之支付数据篡改安全

水平越权 概述&#xff1a;攻击者尝试访问与他拥有相同权限的用户的资源 测试方法&#xff1a;能否通过A用户操作影响到B用户 案例&#xff1a;pikachu-本地水平垂直越权演示-漏洞成因 1&#xff09;可以看到kobe很多的敏感信息 2&#xff09;burp抓包&#xff0c;更改user…

react路由基础

1.目录 A. 能够说出React路由的作用 B. 能够掌握react-router-dom的基本使用 C. 能够使用编程式导航跳转路由 D. 能够知道React路由的匹配模式 2.目录 A. React路由介绍 B. 路由的基本使用 C. 路由的执行过程 D. 编程式导航 E. 默认路由 F. 匹配模式 3.react路由介绍 现代…

USB-C接口:办公新宠,一线连接笔记本与显示器

USB-C接口如今已成为笔记本与显示器连接的优选方案。无需担心正反插错&#xff0c;支持雷电4和DP视频信号输出&#xff0c;高速数据传输&#xff0c;还有最高100W的快充功能&#xff0c;真是方便又实用&#xff01; 一线连接&#xff0c;多功能融合 通过这个接口&#xff0c;你…

Cookie、Session和JWT

摘要&#xff1a;Cookie、Session和JWT都不是什么新的技术了&#xff0c;最近用到了就比较和总结下。 我们知道http协议是无状态的&#xff0c;用户登录后如何验证和保存用户状态呢&#xff1f;下面来介绍 1. 使用Cookie和Session验证登录状态 session是保存在服务端的一种数…

笑营宝高校选修课报名考勤系统源码开发方案

一、项目背景与目标 &#xff08;一&#xff09;项目背景 随着高等教育的普及和教学模式的不断创新&#xff0c;高校选修课程体系日趋复杂多变。学生对课程选择的自由度提高&#xff0c;使得传统的选课和考勤管理方式变得繁琐且效率低下。目前&#xff0c;许多高校仍然采用纸…

Visio使用笔记

记录一下需要的常用操作 圆角矩形的弧度调整 如果一开始创建的是圆角矩形&#xff0c;可以菜单栏先改为矩形 取消箭头的对齐吸附 alt F9&#xff0c;取消勾选 忘记快捷键&#xff0c;可以菜单栏找到视图&#xff0c;点击视觉帮助右下角的小箭头&#xff0c;引出上面的界面…

【OpenGauss源码学习 —— 执行算子(Nest Loop 算子)】

执行算子&#xff08;Nest Loop 算子&#xff09; 概述Nest Loop 算子ExecInitNestLoop 函数ExecNestLoop 函数ExecEndNestLoop 函数ExecReScanNestLoop 函数 总结 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果…

git忽略某些文件(夹)更改说明

概述 在项目中,常有需要忽略的文件、文件夹提交到代码仓库中,在此做个笔录。 一、在项目根目录内新建文本文件,并重命名为.gitignore,该文件语法如下 # 以#开始的行,被视为注释. # 忽略掉所有文件名是 a.txt的文件. a.txt # 忽略所有生成的 java文件, *.java # a.j…

Spring八股 常见面试题

什么是Spring Bean 简单来说&#xff0c;Bean 代指的就是那些被 IoC 容器所管理的对象。我们需要告诉 IoC 容器帮助我们管理哪些对象&#xff0c;这个是通过配置元数据来定义的。配置元数据可以是 XML 文件、注解或者 Java 配置类。 将一个类声明为 Bean 的注解有哪些? Com…

代码异常处理

一、异常格式 错误堆栈信息的格式大致如下&#xff1a; 第一行包含了错误类型&#xff08;Exception或Error&#xff09;和错误描述。 从第二行开始&#xff0c;每一行都表示一个调用栈帧&#xff08;Stack Frame&#xff09;&#xff0c;包含了类名、方法名和代码行号。二、…

c++阶梯之模板初阶

1. 泛型编程 void Swap(int& x, int& y) {int tmp x;x y;y tmp; }void Swap(double& x, double& y) {double tmp x;x y;y tmp; }void Swap(char& x, char& y) {char tmp x;x y;y tmp; } int main() {int a 10, b 20;double c 1.1, d 2.2…

【Intel oneAPI实战】使用英特尔套件解决杂草-农作物检测分类的视觉问题

目录 一、简介&#xff1a;计算机视觉挑战——检测并清除杂草二、基于YOLO的杂草-农作物检测分类2.1、YOLO简介2.2、基于YOLO的杂草-农作物检测分类解决方案 三、基于YOLO的杂草-农作物检测分类系统设计3.1、基于flask框架的demo应用程序后端3.2、基于Vue框架的demo应用程序前端…

MySQL学习Day23——索引优化与查询优化

SQL查询优化的技术有很多&#xff0c;大方向可分为物理查询优化和逻辑查询优化 物理查询优化:通过索引和表连接方式等技术来进行优化; 逻辑查询优化:通过SQL等价变换提升查询效率 一、索引失效案例: 是否使用索引是由优化器决定&#xff0c;优化器基于cost开销而不是规则和…

网络编程:基于TCP和UDP的服务器、客户端

1.基于TCP通信服务器 程序代码&#xff1a; 1 #include<myhead.h>2 #define SER_IP "192.168.126.121"//服务器IP3 #define SER_PORT 8888//服务器端口号4 int main(int argc, const char *argv[])5 {6 //1.创建用于监听的套接字7 int sfd-1;8 sf…

Scaled Dot-Product Attention

Scaled Dot-Product Attention flyfish Attention ( Q , K , V ) softmax ( Q K T d k ) V {\text{Attention}}(Q, K, V) \text{softmax}\left(\frac{QK^{T}}{\sqrt{d_k}}\right)V Attention(Q,K,V)softmax(dk​ ​QKT​)V import torch import torch.nn as nn import torc…

源码框架-​1.Spring底层核心原理解析

目录 Spring中核心知识点: Bean的创建过程 推断构造方法 AOP大致流程 Spring事务 Spring中核心知识点: Bean的生命周期底层原理依赖注入底层原理初始化底层原理推断构造方法底层原理AOP底层原理Spring事务底层原理 ps:这篇文章中都只是大致流程&#xff0c;后续会针对每…

【vuex之五大核心概念】

vuex:五大核心概念 一、state状态1.state的含义2.如何访问以及使用仓库的数据&#xff08;1&#xff09;通过store直接访问获取store对象 &#xff08;2&#xff09;通过辅助函数MapState 二、mutations1.作用2.严格模式3.操作流程定义 mutations 对象&#xff0c;对象中存放修…

IEEE Transactions on Industrial Electronics工业电子TIE修改稿注意事项及提交须知

一、背景 兔年末投了一篇TIE&#xff0c;手稿初次提交的注意事项也整理成了博客IEEE Transactions on Industrial Electronics工业电子TIE论文投稿须知&#xff0c;获得了许多点赞和收藏。最近也收到了审稿结果&#xff0c;给的意见是大修major revision&#xff0c;总之只要不…

FinalShell连接Linux

远程连接linux 我们使用VMware可以得到Linux虚拟机&#xff0c;但是在/Mware中操作Linux的命令行页面不太方便&#xff0c;主要是: 内容的复制、粘贴跨越VMware不方便 文件的上传、下载跨越VMware不方便 不方便也就是和Linux系统的各类交互&#xff0c;跨越VMwar 到Linux操作系…

vue a-table 实现指定字段相同数据合并行

vue a-table 实现相同数据合并行 实现效果代码实现cloums数据格式数据源格式合并代码 实现效果 代码实现 cloums数据格式 const getColumns function () {return [{title: "分类",dataIndex: "checked",width: "150px",customRender: (text, …