Bean生命周期解析

Bean生命周期

小思考-CarService内DemoService是否有值?

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(mainConfig.class);

CarService demo1 = context.getBean("carService", CarService.class);
CarService demo2 = new CarService();
@Service
public class CarService {

	@Autowired
	private DemoService demoService; //是否有值

	public void say(){

		System.out.println("day day up!");
	}

}
@Service
public class CarService {

	private DemoService demoService;
	
	public CarService(DemoService demoService) { //是否有值
		this.demoService = demoService;
	}
}

创建过程

  • 利用该类的构造方法来实例化获得普通对象(推断构造方法)
  • 判断该类中是否有@Autowired等注解,进行属性赋值(DI)
  • 注入后,该对象是否实现BeanNameAware、BeanClassLoaderAware
  • 初始化前(@PostConstruct)
  • 初始化(实现InitializingBean)
  • 初始化后(AOP 代理对象
  • 生成Bean

推断构造方法

若一个类中有多个构造方法,spring将通过推断构造方法进行选择,得到对象。

判断逻辑:
  • 若类中只有一个构造方法,不管是无参还是有参构造方法,都会使用这个构造方法。
  • 若类中有多个构造方法,存在无参构造方法spring就用无参构造方法。不存在无参构造方法,spring会报错。
  • 若在某个构造方法上添加@Autowired注解,spring会使用这个构造方法
例:
@Service
public class CarService {

	private DemoService demoService;

	//无参构造方法
	public CarService() {
	}
     //有参构造方法1
	public CarService(DemoService demoService) {
		this.demoService = demoService;
	}
	//有参构造方法2
	@Autowired
	public CarService(DemoService demoService1,DemoService demoService) {
		this.demoService = demoService;
	}
}

@Autowired注解

@Autowired是sping提供,按byType(类型装配)自动注入
类型匹配一个bean,则无须关注名字
类型匹配多个bean,则通过名字进行查找,也可以使用@Qualifier进行Bean指定

carService.testService();//调用CarService类的方法
	@Bean
	public DemoService demoService(){
		return new DemoService();
	}

	@Bean
	public DemoService demoService1(){
		return new DemoService();
	}

	@Bean
	public DemoService demoService2(){
		return new DemoService();
	}
@Service
public class CarService {

	//这里通过类型会获取三个Bean  demoService,demoService1,demoService2
	//可以根据名字进行匹配 或者 使用 @Qualifier("demoService")
	@Autowired
	private DemoService demoService1;

	public void testService(){

		demoService1.say();
	}
}

代理模式

代理模式(proxy)是一种设计模式,提供了一种对目标对象的访问方式,好处:可以在实现目标对象的基础上,增强对目标对象的操作,扩展目标对象的功能。
代理类继承目标类,对调用目标类

AOP基本流程

  • 生成代理类CarServiceProxy,代理类继承CarService
  • CarServiceProxy重写CarService类中方法,比如CarService中sayHello方法
  • 代理类中携带target对象即普通对象,用target普通对象调用普通对象的方法。
carService.sayHello(); //这里的carService对象就是代理对象
@Component
@Aspect
public class CarAop {

	@Pointcut("execution(* com.mec.deom.CarService.*(..))")
	public void listen(){}

	@Before(value = "listen()")
	public void pointcutTest(JoinPoint joinPoint){
		//打印的target对象为CarService普通对象
		System.out.println(joinPoint.getTarget() instanceof CarService ? ((CarService) joinPoint.getTarget()) : null);
		System.out.println("-------------");
		//执行完后,会执行target.sayHello
	}
}
//最后通过target调用sayHello
public void sayHello(){
		System.out.println("day day up!");
	}

事务Transactation

	//添加@Configuration事务才可以生效---事务管理器和jdbcTemplate需要是同一个数据源(dataSource)
	@Bean
	public JdbcTemplate jdbcTemplate(){
		return new  JdbcTemplate(dataSource());
	}
	@Bean
	public PlatformTransactionManager transactionManager(){
		DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
		dataSourceTransactionManager.setDataSource(dataSource());
		return dataSourceTransactionManager;
	}
	@Bean
	public DataSource dataSource(){
		DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
		driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
		driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/test?setUnicode=true&characterEncoding=utf8");
		driverManagerDataSource.setUsername("root");
		driverManagerDataSource.setPassword("dev123456");
		return driverManagerDataSource;
	}
流程
  • 扫描@Transactional
  • 创建一个数据库连接(事务管理器 dataSource)
  • 修改conn.autocommit = false
  • 执行sql-- target普通方法调用方法
  • commit/rollback
事务传播行为
  • propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
  • propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
  • propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
  • propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
  • propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
  • propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的
事务传播失效场景
carService.testService();
   //当前例子并未抛异常
	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Transactional
	public void testService(){
		jdbcTemplate.execute("insert into user (name,age) values ('test',19)");
		sayHello();
	}

	//Propagation.NEVER 当前事务存在则抛异常
	@Transactional(propagation = Propagation.NEVER)
	public void sayHello(){
		System.out.println("day day up!");
	}
解决方案
@Service
public class CarService {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	//新建类
	@Autowired
	private BaseCarService baseCarService;

	@Transactional
	public void testService(){

		jdbcTemplate.execute("insert into user (name,age) values ('test',19)");
		baseCarService.sayHello();

	}

}
@Component
public class BaseCarService {

	@Transactional(propagation = Propagation.NEVER)
	public void sayHello(){
		System.out.println("day day up!");
	}
}
//异常展示
Exception in thread "main" org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
总结:

一、代理对象来进行事务管理器进行数据库连接,修改autocommit属性,而调用到testService方法时却是普通对象的调用,因此事务传播失效。

二、新建BaseCarService类,当carService普通对象调用sayHello方法时,spring会在IOC容器中找到拥有事务的BaseCarServiceProxy代理类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小阳会武功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值