Spring Bean如何实现实例化呢?

欣喜 Spring 发布时间:2023-12-06 15:14:01 阅读数:12155 1
下文笔者讲述Spring Bean实例化的过程分享,如下所示

Spring简介

Spring是目前最流程的开源框架之一
     可以毫不夸张的说
     Spring是java开发的必备语言
==========================
Spring Bean是Spring中最重要的元素
    也是Spring管理的核心
    那么Spring如何实例化的呢?笔者将一一道来,如下所示 

Spring Bean实例化的步骤

1.类
2.推断选择构造方法(默认调用类无参构造方法)
3.普通对象(new出来)
4.为对象的属性(加了注解的,如@Autowired)进行依赖注入
5.初始化前:判断方法上是否加了@PostConstruct注解
6.初始化:判断是否实现了InitializingBean接口,反射调用afterPropertiesSet方法
7.初始化后:进行AOP
8.代理对象
9.放入单例池Map
10.Bean生成完毕

Spring调用类的构造方法注意事项

Spring调用类的构造方法有以下情况
   Spring默认会调用类的无参构造方法创建类

   仅有的一个有参构造方法(无参构造方法就没有了),Spring会调用该有参构造方法创建类

   两个以上的有参构造方法,Spring报错,因为Spring也不清楚要调用哪个构造方法来创建对象

  两个以上的有参构造方法,并在一个指定的构造方法上加了@Autowired注解,Spring则调用该构造方法来创建对象

容器启动阶段

Bean实例化阶段
容器的启动阶段
     Spring启动前的准备工作,方便后续的实例化操作

容器启动阶段

配置元信息

Spring IOC容器将对象实例的创建与对象实例的使用分离
对象注入到相应的类中,此时我们使用Spring就可以完成相关的事项
<bean id="role" class="com.java265.springxmlbean.entity.Role">
    <!-- property元素是定义类的属性,name属性定义的是属性名称 value是值
    相当于:
    Role role=new Role();
    role.setId(1);
    role.setRoleName("高级工程师");
    role.setNote("重要人员");-->
    <property name="id" value="1"/>
    <property name="roleName" value="高级工程师"/>
    <property name="note" value="重要人员"/>
</bean>

BeanDefination

 xml或其他文件等等配置元信息
   并转换为BeanDefination对象,方便后续生成Bean

BeanDefinationReader

不同的BeanDefinationReader 读取不同格式的数据
   如:xml ,properties,json ,yml,yaml等不同的实现类读取不同的文件

BeanDefinationRegistry

配置元信息加载到内存
   并转化为BeanDefination的形式
   创建某一个对象实例的时候
    找到相应的BeanDefination然后创建对象即可
 
      Spring通过BeanDefinationReader将配置元信息加载到内存生成相应的BeanDefination之后
      将其注册到BeanDefinationRegistry中
        BeanDefinationRegistry就是一个存放BeanDefination中
          采用键值对的形式 
          使用特定的Bean定义的id,映射到相应的BeanDefination。

BeanFactoryPostProcessor

BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点
       主要负责对注册到BeanDefinationRegistry中的
             一个个BeanDefination进行一定程度上的修改与替换

配置Jdbc的DataSource连接

<bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="maxIdle" value="${jdbc.maxIdle}"></property>
    <property name="maxActive" value="${jdbc.maxActive}"></property>
    <property name="maxWait" value="${jdbc.maxWait}"></property>
    <property name="minIdle" value="${jdbc.minIdle}"></property>

    <property name="driverClassName"
        value="${jdbc.driverClassName}">
    </property>
    <property name="url" value="${jdbc.url}"></property>

    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>
BeanFactoryPostProcessor对注册到BeanDefinationRegistry中的BeanDefination做最后的修改
      替换$占位符为配置文件中的真实的数据
      整个容器启动阶段就完成
       容器的启动阶段的最终产物就是注册到BeanDefinationRegistry中的一个个BeanDefination
        此时Spring Bean的实例化已完成

Bean实例化阶段

Bean实例化,我们可以采用懒加载的方式
  也可以立即启动Bean实例化
  或采用getBean方法实例化Bean并保存

对象创建策略

对象创建采用策略模式
   使用BeanDefinationRegistry中的BeanDefination
   可使用反射的方式创建对象
     也可以使用CGlib字节码生成创建对象

BeanWrapper对象

        Spring中的Bean
  由于Spring IOC容器中要管理多种类型的对象
     因此为了统一对不同类型对象的访问
     Spring给所有创建的Bean实例包装了一层
     这个外套就是BeanWrapper
     BeanWrapper实际上是对反射相关API的简单封装
     使得上层使用反射完成相关的业务逻辑大大的简化
      我们要获取某个对象的属性
       调用某个对象的方法
       现在不需要在写繁杂的反射API以及处理一堆麻烦的异常
        直接通过BeanWrapper就可以完成相关操作

设置对象属性

基本类型的属性
    如果配置元信息中有配置
    那么将直接使用配置元信息中的设置值赋值即可
     即使基本类型的属性没有设置值
     那么得益于JVM对象实例化过程
      属性依然可以被赋予默认的初始化零值。

对于引用类型的属性
     Spring会将所有已经创建好的对象放入一个Map结构中
    此时Spring会检查所依赖的对象是否已经被纳入容器的管理范围之内
    也就是Map中是否已经有对应对象的实例了
     如果有
        那么直接注入
     如果没有
        Spring会暂时放下该对象的实例化过程
       转而先去实例化依赖对象
       稍后来完成该对象的实例化过程

检查Aware相关接口

 Aware接口可以将Spring相关信息注册到依赖对象实例中    

BeanPostProcessor前置处理

 
BeanPostProcessor前置处理
   在要生产的Bean实例放到容器之前
    允许我们程序员对Bean实例进行一定程度的修改,替换等操作。

自定义初始化逻辑

在所有的准备工作完成之后
    如果我们的Bean还有一定的初始化逻辑
   那么Spring将允许我们通过两种方式配置我们的初始化逻辑
      (1)  InitializingBean 
      (2)  配置init-method参数 一般通过配置init-method方法比较灵活。

BeanPostProcess后置处理

与前置处理类似
    这里是在Bean自定义逻辑也执行完成之后
     Spring又留给我们的最后一个扩展点

自定义销毁逻辑

(1) 实现DisposableBean接口 
(2) 配置destory-method参数
    如:
       配置dataSource时destory-method为数据库连接的close()方法

调用回调销毁接口

 自定义销毁逻辑
    Spring将以回调的方式调用我们自定义的销毁逻辑
     然后Bean就完成了,此功能很少使用
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaFramework/Spring/202312/7398.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者