对Spring源码的学习:一

news2025/1/19 14:17:39

目录

BeanFactory开发流程

ApplicationContext

BeanFactory与ApplicationContext对比

基于XML方式的Bean的配置

自动装配


BeanFactory开发流程

这里的第三方指的是Spring提供的BeanFactory,Spring启动时会初始化BeanFactory,然后读取配置清单(xml文件)获取需要被加载的bean。实现上面流程图的具体代码如下

创建beans.xml文件

public class Test {
    public static void main(String[] args) {
        //定义出一个bean工厂
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //读取xml文件的读取器
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //读取配置文件
        reader.loadBeanDefinitions("beans.xml");
        UserService userService = (UserService) beanFactory.getBean("userService");
        System.out.println(userService);
    }
}

因为我们在开发中要遵循三层架构,业务层需要定义数据层,那么接下来我们再在xml文件中指定要一个数据层bean。代码如下

public class UserServiceImpl implements UserService {
    //该方法由beanFactory来调用,set注入
    public void setUserDao(UserDao userDao){
        System.out.println("由bean工厂调用该set方法");
    }
}

需要注意的是,需要property标签中的属性的name应该是setXxx()方法中的Xxx第一个子母小写之后的字符,ref标签指的是bean定义的id。接下来我们查看Test类的运行结果

public class Test {
    public static void main(String[] args) {
        //定义出一个bean工厂
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //读取xml文件的读取器
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //读取配置文件
        reader.loadBeanDefinitions("beans.xml");
        UserService userService = (UserService) beanFactory.getBean("userService");
    }
}

执行结果截图 

BeanFactory是Spring中最重要的核心类,下文中的ApplicationContext虽然叫做Spring容器,但实际上在该类中最后调用的还是BeanFactory。

ApplicationContext

ApplicationContext称为Spring容器,内部封装了BeanFactory,比BeanFactory功能更丰富,使用ApplicationContext时,xml文件配置我们习惯叫做applicationContext.xml。接下来是一个示例代码

public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Object userService = context.getBean("userService");
    }
}

BeanFactory与ApplicationContext对比

  1. BeanFactory是Spring的早期接口,称为Spring的Bean工厂,ApplicationContext是后期更高级接口,称之为Spring 容器
  2. ApplicationContext在BeanFactory基础上对功能进行了扩展,例如: 监听功能、国际化功能等。BeanFactory的API更偏向底层,ApplicationContext的API大多数是对这些底层API的封装;
  3. Bean创建的主要逻辑和功能都被封装在BeanFactory中ApplicationContext不仅继承了BeanFactory,而且ApplicationContext内部还维护着BeanFactory的引用,所以,ApplicationContext与BeanFactory既有继承关系,又有融合关系。
  4. Bean的初始化时机不同,原始BeanFactory是在首次调用getBean时才进行Bean的创建,而ApplicationContext则是配置文件加载,容器一创建就将Bean都实例化并初始化好

基于XML方式的Bean的配置

XmI配置方式

功能描述

<bean id="class="">

Bean的id和全限定名配置

<bean name="">

通过name设置Bean的别名,通过别名也能直接获取到Bean实例

<bean scope="">

Bean的作用范围,BeanFactory作为容器时取值singleton和prototype

<bean lazy-init="">

Bean的实例化时机,是否延迟加载。BeanFactory作为容器时无效

<bean init-method="">

Bean实例化后自动执行的初始化方法,method指定方法名

<bean destroy-method="">

Bean实例销毁前的方法,method指定方法名

<bean autowire="byType">

设置自动注入模式,常用的有按照类型byType,按照名字byName

<bean factory-bean="" factory-method=""/>

指定哪个工厂Bean的哪个方法完成Bean的创建

默认情况下,单纯的Spring环境的Bean的作用范围有两个:Singleton与Prototype

  • Singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例。
  • Prototype:原型,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。

Spring实例化Bean的两种方式如下:

一:通过构造方法实例化

默认在xml文件中配置的信息都是调用了无参构造器,但是如果我们需要参数时,需要添加constructor-arg标签,该标签标识向方法中传递参数。

<beans>
  <bean id="userService" class="com.zmt.service.impl.UserServiceImpl">
    <!-- 默认采用无参构造器,但如果需要参数,则需要进行配置 -->
    <constructor-arg name="参数名称" value="参数值"></constructor-arg>
    <property name="userDao" ref="userDao"></property>
  </bean>
  <bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean>
</beans>

二:通过调用自定义的工厂方法对Bean进行实例化

静态工厂方法实例化Bean

public class MyBeanFactory {
    public static UserDao getUserDao(){
        //在实例化Bean之前,我们可以进行一些业务逻辑操作
        return new UserDaoImpl();
    }
}
  <beans>
      <!--指定执行自定义的Bean工厂的指定方法去实例化Bean-->
      <bean id="userDao1" class="com.zmt.factory.MyBeanFactory" factory-method="getUserDao"></bean>

      <bean id="userService" class="com.zmt.service.impl.UserServiceImpl">
          <property name="userDao" ref="userDao"></property>
      </bean>
      <bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean>
  </beans>

可以看到执行结果,一个是通过无参构造器创建出来的Bean一个是通过自定义的静态工厂创建的。

实例工厂方法实例化Bean

与静态工厂方法实例化Bean区别在于,我们需要将工厂类也加载为Bean对象,然后通过该Bean对象去实例化

public class MyBeanFactory1 {
    public UserDao getUserDao(){
        //在实例化Bean之前,我们可以进行一些业务逻辑操作
        return new UserDaoImpl();
    }
}
<beans>
  <!--加载工厂Bean-->
  <bean id="myBeanFactory1" class="com.zmt.factory.MyBeanFactory1"></bean>
  <!--通过工厂Bean去获取需要的对象-->
  <bean id="userDao2" factory-bean="myBeanFactory1" factory-method="getUserDao"></bean>
  <!--指定执行自定义的Bean工厂的指定方法去实例化Bean-->
  <bean id="userDao1" class="com.zmt.factory.MyBeanFactory" factory-method="getUserDao"></bean>

  <bean id="userService" class="com.zmt.service.impl.UserServiceImpl">
    <property name="userDao" ref="userDao"></property>
  </bean>
  <bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean>
</beans>

实现FactoryBean规范延迟实例化Bean

//需要指定FactoryBean的泛型
public class MyBeanFactory2 implements FactoryBean<UserDao> {
    //该方法在执行getBean的时候去执行
    @Override
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

    //获取该Bean工厂产生的Bean类型
    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }
}
  <beans>
      <!--Bean名称是userDao3,但加载的是工厂类-->
      <bean id="userDao3" class="com.zmt.factory.MyBeanFactory2"></bean>

      <!--加载工厂Bean-->
      <bean id="myBeanFactory1" class="com.zmt.factory.MyBeanFactory1"></bean>
      <!--通过工厂Bean去获取需要的对象-->
      <bean id="userDao2" factory-bean="myBeanFactory1" factory-method="getUserDao"></bean>
      <!--指定执行自定义的Bean工厂的指定方法去实例化Bean-->
      <bean id="userDao1" class="com.zmt.factory.MyBeanFactory" factory-method="getUserDao"></bean>

      <bean id="userService" class="com.zmt.service.impl.UserServiceImpl">
          <property name="userDao" ref="userDao"></property>
      </bean>
      <bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean>
  </beans>

延迟加载Bean实际上是先加载了工厂Bean类,当需要用到Bean时,会从单例池中获取FactoryBean后调用该对象中的getObject()方法获取到真正的的Bean对象,并将该Bean对象缓存在factoryBeanObjectCache中,当使用到该Bean对象时从该Map中获取。

自动装配

我们通过编写property标签进行的注入叫做手动注入,而自动装配是不需要编写property标签的,而是在bean标签中使用autowire属性来实现自动注入,aotuwire的值有两个:byName、byType

  • byName:通过属性名自动装配,去匹配setXxx与id="xxx"是否一致
  • byType:通过Bean的类型从容器中匹配,匹配出多个相同Bean类型时,报错

UserServiceImpl存在一个setUserDao方法,因此我们可以这么编写,同样可以将属性注入到UserServiceImpl中

<beans>
    <bean id="userService" class="com.zmt.service.impl.UserServiceImpl" autowire="byName"></bean>
    <bean id="userDao" class="com.zmt.dao.impl.UserDaoImpl"></bean>
</beans>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1293581.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

元宇宙:重塑游戏行业体验下一个前沿

游戏行业在其整个历史中经历了显著的转变&#xff0c;从超级马里奥的像素化冒险发展到Red Dead Redemption等游戏中迷人的开放世界体验。随着时间的推移&#xff0c;游戏不断突破数字领域所能达到的极限。然而&#xff0c;被称为元宇宙的突破性演变将彻底改变游戏行业&#xff…

【复杂gRPC之Java调用go】

1 注意点 一般上来说如果java调用java的话&#xff0c;我们可以使用springcloud来做&#xff0c;而面对这种跨语言的情况下&#xff0c;gRPC就展现出了他的优势。 代码放在这了&#xff0c;请结合前面的go服务器端一起使用 https://gitee.com/guo-zonghao/java-client-grpc /…

2-4、DEBUG和源程序区别

语雀原文链接 文章目录 1、DEBUG 和 汇编编译器MASM区别1&#xff1a;默认进制不同区别2&#xff1a;[地址]示例1&#xff1a;debug示例2&#xff1a;[0]示例3&#xff1a;[寄存器]示例4&#xff1a;ds:[0]小结 区别3&#xff1a;源程序数据不能以字母开头 1、DEBUG 和 汇编编…

labelme等标注工具/数据增强工具输出JSON文件格式检查脚本

标注的文件太多了&#xff0c;还有用数据增强工具生成了一票的新数据。在转换或使用训练时候会报错&#xff0c;错误原因是json中语法有问题&#xff0c;这样会中断程序运行&#xff0c;调试造成很大困扰。 检查确实最后有问题&#xff0c;多写了一次 写一个脚本&#xff0c;用…

机器学习应用 | 使用 MATLAB 进行异常检测(下)

在使用MATLAB 进行异常检测&#xff08;上&#xff09;中&#xff0c;我们探讨了什么是异常值&#xff0c;简单的一维数据异常检测问题&#xff0c;针对高维数据的有监督异常检测方法。 在&#xff08;下&#xff09;篇中&#xff0c;我们将和大家一起探讨无监督异常检测。 没…

Unity 状态系统

状态系统 原理食用方法Demo 原理 #mermaid-svg-lUbxJ8eMP3KqrEhY {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-lUbxJ8eMP3KqrEhY .error-icon{fill:#552222;}#mermaid-svg-lUbxJ8eMP3KqrEhY .error-text{fill:#55…

算法通关村第十八关-青铜挑战回溯是怎么回事

大家好我是苏麟 , 今天聊聊回溯是怎么个事 . 回溯是最重要的算法思想之一&#xff0c;主要解决一些暴力枚举也搞不定的问题&#xff0c;例如组合、分割、子集、排列&#xff0c;棋盘等。从性能角度来看回溯算法的效率并不高&#xff0c;但对于这些暴力都搞不定的算法能出结果就…

快速排序的非递归实现

上期我们实现了快速排序的递归实现&#xff0c;但是我们知道如果递归深度太深&#xff0c;栈就会溢出&#xff0c;所以我们本期将为大家讲述快速排序的非递归实现&#xff0c;我们需要用到栈的数据结构&#xff0c;我们知道栈中的数据全是在堆区开辟的空间&#xff0c;堆的空间…

【EXCEL】offset函数

语法&#xff1a; offset(reference,row,column,[height],[width]) 例子&#xff1a;

【日常总结】mybatis-plus WHERE BINARY 中文查不出来

目录 一、场景 二、问题 三、原因 四、解决方案 五、拓展&#xff08;全表全字段修改字符集一键更改&#xff09; 准备工作&#xff1a;做好整个库备份 1. 全表一键修改 Stage 1&#xff1a;运行如下查询 Stage 2&#xff1a;复制sql语句 Stage 3&#xff1a;执行即可…

Volumetric Lights 2 HDRP

高清晰度渲染管道,包括先进的新功能,如半透明阴影图和直接灯光投射加上许多改进。 插件是一个快速,灵活和伟大的前瞻性光散射解决方案的高清晰度渲染管道。只需点击几下,即可改善场景中的照明视觉效果。 兼容: 点光源 聚光灯 碟形灯 矩形灯 通过覆盖摄像机周围大面积区域的…

05 JQuery基础入门

文章目录 一、jQuery介绍1. 简介2. 版本介绍3. 相关网站4. HTML引入方式 二、基础语法1. 顶级对象$2. 与DOM对象转化3. 选择器4. 事件5. 动画6. 修改样式7. 修改属性 一、jQuery介绍 1. 简介 jQuery是JavaScript编程语言底层库&#xff0c;它是一个快速&#xff0c;简洁的Jav…

JavaScript <关于逆向RSA非对称加密算法的案例(附原代码)>--案例(五)

前言: 趁热打铁,标记一下RSA的算法逆向...第二篇会有详解(本篇重在过程) 正文: 废话不说,直接分析步骤图: 到了这里,可以看到在登录的时候,需要验证码(本篇不教反验证码) 下面是正题--->逆他的pwd(密码) 总结: 问题:怎么确定一个密文数据是基于什么算法做出来的呢? 答:…

python 涉及opencv mediapipe知识,眨眼计数 供初学者参考

基本思路 我们知道正面侦测到人脸时&#xff0c;任意一只眼睛水平方向上的两个特征点构成水平距离&#xff0c;上下两个特征点构成垂直距离 当头像靠近或者远离摄像头时&#xff0c;垂直距离与水平距离的比值基本恒定 根据这一思路 当闭眼时 垂直距离变小 比值固定小于某一个…

Abaqus基础教程--胶合失效仿真

胶合是电子行业中常见的连接方式&#xff0c;abaqus中常用cohesive单元或者cohesive接触两种方法进行胶合失效仿真&#xff0c;这两种方式操作方法有所差别&#xff0c;但结果一般大同小异。 本例模型比较简单&#xff0c;建模过程从略&#xff0c;使用静态分析&#xff0c;使…

python基于ModBusTCP服务端的业务实现特定的client

python实现ModBusTCP协议的client是一件简单的事情&#xff0c;只要通过pymodbus、pyModbusTCP等模块都可以实现&#xff0c;本文采用pymodbus。但要基于ModBusTCP服务端的业务实现特定的client&#xff0c;那得看看服务端是否复杂。前面系列文章&#xff0c;我们学习了对服务端…

【vtkWidgetRepresentation】第五期 vtkLineRepresentation

很高兴在雪易的CSDN遇见你 内容同步更新在公众号“VTK忠粉” 【vtkWidgetRepresentation】第五期 一条直线的交互 前言 本文分享vtkLineRepresentation&#xff0c;希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易会继续努力分享&#xf…

Python---继承

1、什么是继承 我们接下来来聊聊Python代码中的“继承”&#xff1a;类是用来描述现实世界中同一组事务的共有特性的抽象模型&#xff0c;但是类也有上下级和范围之分&#xff0c;比如&#xff1a;生物 > 动物 > 哺乳动物 > 灵长型动物 > 人类 > 黄种人 从哲学…

Go--协程

协程 协程是Go语言最大的特色之一。 1、协程的概念 协程并不是Go发明的概念&#xff0c;支持协程的变成语言有很多。Go在语言层面直接提供对协程的支持称为goroutine。 1.1 基本概念 进程 进程是应用程序启动的实例&#xff0c;每个进程都有独立的内存空间&#xff0c;不同…

DSP外部中断笔记

中断原理 三部分 注意 &#xff0c;外部中断使能&#xff0c;PIE使能&#xff0c;CPU中断使能 外部中断有7个&#xff0c;PIE有12组&#xff0c;一个组有8个中断复用。只有一个CPU中断可执行。 外部中断原理 1、外部中断概述 外部中断结构图 外部中断XINT1对应的是0到31GPI…