Spring底层源码分析

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.方法

  • 32
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值