欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

spring生命周期和bean生命周期,spring bean生命周期 简书

终极管理员 知识笔记 120阅读
Bean的生命周期概述

入门使用的Spring代码

ClassPathXmlApplicationContext context  new ClassPathXmlApplicationContext(spring.xml);UserService userService  (UserService) context.getBean(userService);userService.test();

思考问题

1、第一行代码都做了哪些事情

2、第二行代码getBean()如何实现的返回的UserService对象和new创建的对象有什么区别

在新版的Spring MVCSpring Boot的底层主要用的都是AnnotationConfigApplicationContext

AnnotationConfigApplicationContext context  new AnnotationConfigApplicationContext(AppConfig.class);UserService userService  (UserService) context.getBean(userService);userService.test();

注意AppConfig.classspring.xml的本质是一样的都表示Spring的配置类比两种写法

spring.xml中的内容为<context:component-scan base-packagecom.gax/><bean iduserService classcom.gax.service.UserService/>    AppConfig中的内容为ComponentScan(com.gax)public class AppConfig {    Bean    public UserService userService(){    return new UserService();    }}

目前spring.xml这种方式已经很少见了更多的是使用Spring MVC或者Spring Boot这两种也是基于spring.xml这种方式在内部创建一个ApplicationContext但是也有区别

1、Spring MVC创建的是XmlWebApplicationContextClassPathXmlApplicationContext类似都是基于XML配置的

2、Spring Boot创建的是AnnotationConfigApplicationContext

后续重点学习研究的是AnnotationConfigApplicationContext这一种

Spring中是如何创建一个对象

AnnotationConfigApplicationContext可以简单理解为创建Java对象当调用context.getBean(userService)方法时创建一个对象。那么问题来了方法内部如何知道userService对应的是UserService类呢

可以分析出来AnnotationConfigApplicationContext的构造方法做的一些事情

1、解析AppConfig.class得到扫描路径

2、遍历扫描路径下的所有Java类如果类上面有Component、Service等注解那么Spring就会把这个类记录下来存放在一个Map里比如像Map<String, Class>Spring源码中叫BeanDefinitionMap

3、Spring根据规则生成当前类的beanName作为存入Map时的key当前类作为存入Map时的valueSpring中的beanName默认是类名首字母小写

Bean的创建过程

Spring到底是如何来创建一个Bean的呢也就是Bean创建的生命周期。大致流程如下

1、利用该类的构造方法来实例化得到一个对象有多个构造方法时Spring会做出选择推断构造方法

2、得到一个对象后Spring会判断该对象中是否存在被Autowired注解了的属性把这些属性找出来并由Spring进行赋值依赖注入

3、依赖注入后Spring会判断该对象是否实现了BeanNameAware接口、BeanClassLoaderAware接口、BeanFactoryAware接口如果实现了就表示当前对象必须实现该接口中所定义的setBeanName()、setBeanClassLoader()、 setBeanFactory()方法那Spring就会调用这些方法并传入相应的参数Aware回调

4、Aware回调后Spring会判断该对象中是否存在某个方法被PostConstruct注解了如果存在Spring会调用当前对象的此方法初始化前

5、Spring会判断该对象是否实现了InitializingBean接口如果实现了就表示当前对象必须实现该接口中的afterPropertiesSet()方法那Spring就会调用当前对象中的afterPropertiesSet()方法初始化

6、Spring会判断当前对象需不需要进行AOP如果不需要那么Bean就创建完了如果需要进行AOP则会进行动态代理并生成一个代理对象做为Bean初始化后

注意不用AOP时Bean就是构造方法创建的普通对象需要AOP时Bean是代理类实例化的对象

Bean对象创建完成后如果是单例Bean就放在Map里下次可以直接从Map中直接获取Spring源码中Map就是单例池如果是原型Bean就不用放在Map里下次重新创建

推断构造方法

选择构造方法的判断逻辑

1、只有一个构造方法无论是否有参Spring都会选择这个

2、有多个构造方法时Spring会选择无参的构造方法无参本身就是一种默认

没有无参构造方法且构造方法上面都没有Autowired注解时报错Spring不知道选择哪一个

没有无参构造方法但是某个构造方法上面添加了Autowired注解Spring选择这一个构造方法

注意Spring选择有参构造方法时Spring会先根据参数类型类型相同再根据参数名字去找Bean对象类型和名字都找不到就报错

推断构造方法确定用哪个构造方法确定入参的Bean对象

AOP大致流程

判断当前Bean对象需不需要进行AOP

1、找出所有的切面Bean

2、遍历切面中的每个方法看是否写了Before、After等注解

3、如果写了则判断所对应的Pointcut是否和当前Bean对象的类匹配

4、如果匹配则表示当前Bean对象有匹配的的Pointcut需要进行AOP

利用cglib进行AOP的大致流程cglib说白了就是父子类

1、生成代理类XXServiceProxy代理类继承XXService

2、代理类中重写了父类的方法

3、代理类中有一个target属性该属性的值为被代理对象

这里的被代理对象是推断构造方法实例化的对象完成了依赖注入、初始化等

4、代理类中的方法被执行时先执行before的切面逻辑再执行target.目标方法

注意XXServiceProxy是代理类它实例化出来的是代理对象target是被代理对象

思考代理对象的属性是null没有进行依赖注入为什么

没有必要大部分情况用不到需要用的话也可以通过target获取

Spring事务

在某个方法上加了Transactional注解后就表示该方法在调用时会开启Spring事务而这个方法所在的类所对应的Bean对象会是该类的代理对象。

1、判断当前执行的方法是否存在Transactional注解

2、如果存在则利用事务管理器TransactionMananger新建一个数据库连接

3、修改数据库连接的autocommit为false

4、执行target.目标方法业务逻辑的sql

5、执行完之后没有异常则提交否则回滚

事务失效的场景分析

1、调用目标方法的是否为代理类使用代理类调用时才有切面的逻辑

2、是否使用的同一个事务管理器或者说是否同一个数据库连接

标签:
声明:无特别说明,转载请标明本文来源!