Spring: Bean的创建原理解析

这篇具有很好参考价值的文章主要介绍了Spring: Bean的创建原理解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、Spring创建Bean流程

Spring: Bean的创建原理解析
1.读取Bean的定义信息
通过BeanDefinitionReader这个接口解析xml配置、配置类或其他的一些方式定义的类,得到BeanDefinition(Bean定义信息)

2.实例化Bean
通过BeanPostProcessor这个接口(增强器)可以对我们的BeanDefinition进行一些修改,然后BeanFactory通过反射实例化Bean对象,但是此时的Bean对象还没有进行初始化,没有填充属性等操作。

3.初始化Bean
(1)自定义属性赋值是用 set 方法赋值(populateBean())
(2)容器对象的属性赋值是用实现Aware接口的方式来赋值(invokeAwareMethods()),如BeanNameAware
(3)调用BeanPostProcessor的前置处理方法
(4)调用init初始化方法:init-method
(5)调用BeanPostProcessor的后置处理方法(AOP在这里实现)
(6)获得一个完整的对象,并将对象放入map中(通过Context.getBean()可以获取到Bean对象并使用)

4.销毁Bean
Spring容器关闭时会调用DisposableBean的Destory()方法
如果你在这个Bean中配置了destory-method属性,会自动调用指定的销毁方法

二、Bean的整体创建流程

Spring: Bean的创建原理解析

  • 1.利用该类的构造方法来实例化得到一个对象(但是如果一个类中有多个构造方法, Spring则会进行选择,这个叫做推断构造方法,下文在详细介绍)
  • 2.得到一个对象后,Spring会判断该对象中是否存在被@Autowired注解了的属 性,把这些属性找出来并由Spring进行赋值(依赖注入)
  • 3.依赖注入后,Spring会判断该对象是否实现了BeanNameAware接口、 BeanClassLoaderAware接口、BeanFactoryAware接口,如果实现了,就表示当前 对象必须实现该接口中所定义的setBeanName()、setBeanClassLoader()、 setBeanFactory()方法,那Spring就会调用这些方法并传入相应的参数
  • 4.Aware回调后,Spring会判断该对象中是否存在某个方法被@PostConstruct注解 了,如果存在,Spring会调用当前对象的此方法(初始化前),上面的代码中初始化了一个adminUser的数据。
  • 5.紧接着,Spring会判断该对象是否实现了InitializingBean接口,如果实现了,就 表示当前对象必须实现该接口中的afterPropertiesSet()方法,那Spring就会调用当
    前对象中的afterPropertiesSet()方法(初始化)
  • 6.最后,Spring会判断当前对象需不需要进行AOP,如果不需要那么Bean就创建完 了,如果需要进行AOP,则会进行动态代理并生成一个代理对象做为Bean(初始化 后)
    关于第6步控制台没办法打出日志,因为初始后涉及到spring的源码操作,但是可以通过断点看一下,提一句例子中UserService是被LogAspect切面切的。

这样,一个Bean就创建完了,如果当前Bean是单例Bean,那么会把该Bean对象存入一个Map<String, Object>,Map的key为beanName,value为Bean对象。这样下次getBean时就可 以直接从Map中拿到对应的Bean对象了。(实际上,在Spring源码中,这个Map就 是单例池)
如果当前Bean是原型Bean,那么后续没有其他动作,不会存入一个Map,下次 getBean时会再次执行上述创建过程,得到一个新的Bean对象。

三、推断构造方法

至此,我们清楚了Bean的创建流程,那如果UserService中有多个构造函数呢?第一步还能顺利的创建一个普通对象吗?这里面涉及到一个概念推断构造方法,就是spring会去推断用哪个构造方法来创建出普通对象。

总结下:

  • 如果一个类只有一个构造方法,那么没得选择,只能用这个构造方法。但是有参的构造方法,参数必须是spring的Bean这样spring才能拿到进行赋值。
  • 如果一个类存在多个构造方法,Spring不知道如何选择,就会看是否有无参的构 造方法,因为无参构造方法本身表示了一种默认的构造方法。
  • 如果都没有构造方法,就是用默认的无参构造方法来创建。
  • 其实多个构造函数,也可以手动指定告诉spring用哪个构造函数来创建,那就是加了@Autowired注解

四、依赖注入流程

不管是属性注入还是构造方法注入,能提供的信息只有两个一个是类型OrderService ,一个是名字orderService。那到底是根据类型注入的还是根据名字注入的呢?
假设根据名字注入的那刚好有一个其他类型的Bean名字也叫orderService那注入的时候岂不是会类型不匹配异常。比如说刚好有一个OrderBaseService类但是beanName也叫orderService,如果根据名字注入的话拿到的是OrderBaseService对象显然类型不匹配。所以注入通常是先根据类型来查找的:

  • 先根据入参类型找,如果只找到一个不用管name,那就直接用来作为入参
  • 如果根据类型找到多个,则再根据入参名字来确定唯一
  • 最终如果没有找到,则会报错,无法创建当前Bean对象

五、代理对象生成

代理对象通常是AOP的时候会生成代理对象还有一种就是开启事务的时候也会生成代理对象。否则的话Bean都是直接根据构造函数生成对象在进行依赖注入和初始化等流程。

1.AOP代理对象生成

AOP就是进行动态代理,在创建一个Bean的过程中,Spring在最后一步会去判断当前正在 创建的这个Bean是不是需要进行AOP,如果需要则会进行动态代理。

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

  • 1.找出所有的切面Bean
  • 2.遍历切面中的每个方法,看是否写了@Before、@After等注解
  • 3.如果写了,则判断所对应的Pointcut是否和当前Bean对象的类是否匹配
  • 4.如果匹配则表示当前Bean对象有匹配的的Pointcut,表示需要进行AOP

利用cglib进行AOP的大致流程:

  • 1.生成代理类UserServiceProxy,代理类继承UserService
  • 2.代理类中重写了父类的方法,比如UserService中的test()方法
  • 3.代理类中还会有一个target属性,该属性的值为被代理对象(也就是通过 UserService类推断构造方法实例化出来的对象,进行了依赖注入、初始化等步骤的 对象)
  • 4.代理类中的test()方法被执行时的逻辑如下:
    • a. 执行切面逻辑(@Before)
    • b. 调用target.test()
      当我们从Spring容器得到UserService的Bean对象时,拿到的就是UserServiceProxy所生 成的对象,也就是代理对象。
      UserService代理对象.test()—>执行切面逻辑—>target.test(),注意target对象不是代理 对象,而是被代理对象。

2.事务代理对象生成

Spring事务 当我们在某个方法上加了@Transactional注解后,就表示该方法在调用时会开启Spring事 务,而这个方法所在的类所对应的Bean对象会是该类的代理对象。
Spring事务的代理对象执行某个方法时的步骤:

  • 1.判断当前执行的方法是否存在@Transactional注解
  • 2.如果存在,则利用事务管理器(TransactionMananger)新建一个数据库连接,
  • 3.修改数据库连接的autocommit为false
  • 4.执行target.test(),执行程序员所写的业务逻辑代码,也就是执行sql
  • 5.执行完了之后如果没有出现异常,则提交,否则回滚

注意:Spring事务是否会失效的判断标准:某个加了@Transactional注解的方法被调用时,要判 断到底是不是直接被代理对象调用的,如果是则事务会生效,如果不是则失效。

总结

Spring中Bean的创建过程其实就是从一个普通对象蜕变成Bean的一个过程,蜕变包括依赖注入,初始化等步骤。最后在看下这个类是否有被AOP或开启事务有的话会额外生成代理对象作为Bean。

其他

参考:https://www.jianshu.com/p/57ed586e258c
https://www.csdn.net/tags/MtjaYgxsOTU3NTMtYmxvZwO0O0OO0O0O.html文章来源地址https://www.toymoban.com/news/detail-455097.html

到了这里,关于Spring: Bean的创建原理解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring 】执行流程解析:了解Bean的作用域及生命周期

     哈喽,哈喽,大家好~ 我是你们的老朋友: 保护小周ღ    今天给大家带来的是 Spring 项目的执行流程解析  和 Bean 对象的6 种作用域 以及 生命周期 , 本文将为大家讲解,一起来看看叭~ 本期收录于博主的专栏 :JavaEE_保护小周ღ的博客-CSDN博客 适用于编程初学者,感兴趣

    2024年02月16日
    浏览(39)
  • 【Spring】(三)Spring 使用注解存储和读取 Bean对象

    前面的文章详细的介绍了 Spring 对象的创建,以及对 Bean 对象的存取操作,但是通过配置文件注册 Bean 对象以及使用 ApplicationContext 或 BeanFactory 的方式获取 Bean 对象的操作就显得格外的复杂。因此,本文主要就是详细介绍了一种更加简单的方式来实现对 Bean 对象更加简单的储

    2024年02月14日
    浏览(37)
  • 【Spring】使用注解读取和存储Bean对象

     哈喽,哈喽,大家好~ 我是你们的老朋友: 保护小周ღ    谈起Java 圈子里的框架,最年长最耀眼的莫过于 Spring 框架啦,本期给大家带来的是:  将对象存储到 Spring 中、Bean 对象的命名规则、从Spring 中获取bean 对象、注入的、@Autowired 与 @Resource 的区别、解决@Bean 方

    2024年02月13日
    浏览(45)
  • Spring中Bean对象的存储与读取

    在项目的 pom.xml 中添加 Spring 支持 如何选定版本环境:打开官网,点击github图标 jdk8最后一个Spring版本是5.3.x,Spring6.0.x最低需要jdk17 版本冲突问题Maven自己处理 version : 可以选择带有 RELEASE结尾或者纯数字结尾,这样的版本更稳定 项目下创建一个main方法的启动类 存储 Bean 之前

    2024年01月24日
    浏览(35)
  • Spring更简单的存储和读取Bean对象

    目录 1.第一个Spring项目 2.存储Bean对象 2.1 准备工作 2.2 五大类注解 2.3 方法注解@Bean 2.4 Bean对象的默认命名规则 3. 读取Bean对象 3.1 属性注入 3.2 setter注入 3.3 构造方法注入 3.4 注入异常问题 3.5 注入方式优缺点 3.6 @Autowired和@Resource的区别 在学习更简单的方式来读取和存储Bean对象

    2024年02月03日
    浏览(49)
  • Spring(二):更简单的存储与读取 Bean

    通过上一章的Spring,我们基本实现了Spring 的读取与存储,但是在操作过程中,读取与存储并没有那么得“简单” 一套流程还是很复杂,所以,本章来介绍更加简单得读取与存储。 在 Spring 中想要更简单的存储和读取对象的核⼼是使⽤注解,也就是我们接下来要学习 Spring 中的

    2024年02月15日
    浏览(35)
  • 使用Spring的五大类注解读取和存储Bean

    目录 1.存储Bean对象的注解 1.1 五大类注解 1.2 方法注解 1.3添加注解的依赖 2.注解的使用 2.1  controller注解 2. 2Service注解  2.3.Resopsitory注解 2.4Component注解 2.5Configuration注解 2.6 注解之间的关系 3.方法注解 3.1 方法注解要配合类注解来使用。 3.2 重命名Bean 4.获取Bean对象(对象装配

    2024年02月01日
    浏览(39)
  • spring启动流程 (2) Bean实例化流程

    本文通过阅读Spring源码,分析Bean实例化流程。 上一篇文章已经介绍,Bean实例化入口在AbstractApplicationContext类的finishBeanFactoryInitialization方法: 返回指定beanName的(原始)单例对象,如果没有则创建一个新对象: 创建Bean实例、填充属性、调用后置处理器等:

    2024年02月11日
    浏览(80)
  • Spring中Bean加载流程

    BeanDefinition 1.1什么是BeanDefinition? 1.2 BeanDifinition中重要的属性 1.3 BeanDefinition的解析 BeanFactory 2.1 什么是BeanFactory? 2.2 BeanFactory工作流程: Bean生命周期 3.1 什么是Bean生命周期? Bean生命周期是Spring中一个Bean创建过程和销毁过程中所经历的步骤,其中Bean创建过程是重点。 3.2 核

    2024年02月09日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包