Spring创建Bean实例的方式

2023-11-19

目录

简介

源码分析

resolveBeforeInstantiation创建Bean实例

doCreateBean创建Bean实例

Supplier创建实例

FactoryMethod创建实例

自动装配构造函数创建实例

 无参构造函数创建实例

总结


简介

在Spring框架中创建Bean的流程步骤可归纳为getBean -> doGetBean -> createBean -> doCreateBean,其中createBean的核心逻辑就是创建Bean实例。下面通过源码分析来查看具体有几种方式可以创建Bean实例。

源码分析

createBean源码

/**
 * Central method of this class: creates a bean instance,
 * populates the bean instance, applies post-processors, etc.
 * @see #doCreateBean
 */
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;
	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}
	// Prepare method overrides.
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}
	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}
	try {
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
		// A previously detected exception with proper bean creation context already,
		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}

一般情况下创建Bean实例是通过doCreateBean方法来创建的,但是Spring也会给BeanPostProcessors一个机会来返回代理来替代目标实例,就是通过resolveBeforeInstantiation方法来处理这一逻辑,下面通过代码演示resolveBeforeInstantiation是怎样创建Bean实例的。

resolveBeforeInstantiation创建Bean实例

创建User对象

public class User {

	private String name;

	private String address;

	public User() {
	}

	public User(String name, String address) {
		this.name = name;
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "User{" +
				"name='" + name + '\'' +
				", address='" + address + '\'' +
				'}';
	}
}

创建后置处理器

public class UserInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessBeforeInstantiation方法");
		if (beanClass == User.class){
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(beanClass);
			enhancer.setCallback(new UserMethodInterceptor());
			User user = (User) enhancer.create();
			user.setAddress("深圳");
			user.setName("咩哥");
			System.out.println("创建代理对象:" + user);
			return user;
		}
		return null;
	}

	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessAfterInstantiation方法");
		return false;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessBeforeInitialization方法");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessAfterInitialization方法");
		return bean;
	}

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
		System.out.println("beanName:" + beanName + " ----执行postProcessProperties方法");
		return pvs;
	}
}

创建cglib的回调类

public class UserMethodInterceptor implements MethodInterceptor {

	@Override
	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
		System.out.println("目标方法执行之前:" + method);
		Object o1 = methodProxy.invokeSuper(o, objects);
		System.out.println("目标方法执行之后:" + method);
		return o1;
	}
}

创建配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="user" class="com.miege.bean.User"></bean>
    <bean id="myInstantiationAwareBeanPostProcessor" class="org.springframework.resolveBeforeInstantiation.UserInstantiationAwareBeanPostProcessor"></bean>
</beans>

测试类

public class Test {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("resolveBeforeInstantiation.xml");
		User user = (User) ac.getBean("user");
		System.out.println("user:" + user);
	}

}

doCreateBean创建Bean实例

在doCreateBean中调用了一个方法createBeanInstance,这个方法就是创建Bean实例的地方,在这个方法中会通过不同的策略来创建Bean实例。

createBeanInstance源码

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	// Make sure bean class is actually resolved at this point.
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
		throw new BeanCreationException(mbd.getResourceDescription(), beanName,
				"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
	}
	// 判断是否包含实例供应器,如果有,则用其回调方法创建Bean实例
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	if (instanceSupplier != null) {
		return obtainFromSupplier(instanceSupplier, beanName);
	}
	// 判断是否有工厂方法,如果有,则用工厂方法创建Bean实例
	if (mbd.getFactoryMethodName() != null) {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}
	// Shortcut when re-creating the same bean...
	// 防止创建相同的Bean
	boolean resolved = false;
	// 自动装配
	boolean autowireNecessary = false;
	if (args == null) {
		synchronized (mbd.constructorArgumentLock) {
			// 有构造参数或工厂方法
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				resolved = true;
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	if (resolved) {
		// 有构造参数创建Bean实例
		if (autowireNecessary) {
			return autowireConstructor(beanName, mbd, null, null);
		}
		else {
			// 默认的无构造函数创建Bean实例
			return instantiateBean(beanName, mbd);
		}
	}
	// Candidate constructors for autowiring?
	// 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
		return autowireConstructor(beanName, mbd, ctors, args);
	}
	// Preferred constructors for default construction?
	ctors = mbd.getPreferredConstructors();
	if (ctors != null) {
		// 有构造参数创建Bean实例
		return autowireConstructor(beanName, mbd, ctors, null);
	}
	// No special handling: simply use no-arg constructor.
	// 无参构造函数创建对象
	return instantiateBean(beanName, mbd);
}

在这个方法中首先判断是否包含实例供应器,如果有则会通过其中的回调方法来创建实例,否则往下判断是否有工厂方法,没有工厂方法再选择是使用无参构造函数还是有参构造函数创建实例。

Supplier创建实例

创建实例的回调类

public class UserSupplier {

	public static User createUser(){
		return new User("咩哥", "深圳");
	}
}

创建BFPP,BeanFactoryPostProcessor是对BeanDefinition的增强

public class UserSupplierBfpp implements BeanFactoryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		GenericBeanDefinition user = (GenericBeanDefinition) beanFactory.getBeanDefinition("user");
		user.setBeanClass(User.class);
		user.setInstanceSupplier(UserSupplier::createUser);
	}
}

创建xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="user" class="com.miege.bean.User"></bean>
	<bean class="org.springframework.supplier.UserSupplierBfpp"></bean>
</beans>

FactoryMethod创建实例

创建factoryMethod,定义了三个工厂方法,为啥Spring依然能精确找到我们需要的方法呢,因为Spring在选择方法的时候会先筛选出类中所有符合条件的方法(是否是静态的&是否是我们指定的工厂方法),再符合条件的方法中再选择差异化最小的方法

public class UserFactoryMethod {

	public static User getUser(String name, String address) {
		return new User(name, address);
	}

	public static User getUser(String name) {
		User user = new User();
		user.setName(name);
		return user;
	}

	public static User getUser() {
		return new User();
	}
}

创建xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="user" class="org.springframework.factoryMethod.UserFactoryMethod" factory-method="getUser">
		<constructor-arg value="咩哥" ></constructor-arg>
		<constructor-arg value="深圳" ></constructor-arg>
	</bean>
</beans>

自动装配构造函数创建实例

在实体类中的构造方法加@Autowired即可

public class User {

	private String name;

	private String address;

	public User() {
	}

	@Autowired
	public User(String name, String address) {
		this.name = name;
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "User{" +
				"name='" + name + '\'' +
				", address='" + address + '\'' +
				'}';
	}
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="com.miege.bean"></context:component-scan>
	<bean id="user" class="com.miege.bean.User">
		<constructor-arg value="咩哥" ></constructor-arg>
		<constructor-arg value="深圳" ></constructor-arg>
	</bean>
</beans>

 无参构造函数创建实例

修改有参构造方式的xml文件即可

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="user" class="com.miege.bean.User">
	</bean>
</beans>

总结

一共列举出五种创建Bean实例的方式,但Spring创建对象的流程还远远不止,Spring创建Bean实例可用以下流程图概况:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring创建Bean实例的方式 的相关文章

  • Spring Security 上的组和 acl

    我想使用 Spring Security 来管理用户 组和权限 我想使用 ACL 来保护我的域对象 但我找不到将组分配给 acl 的方法 例如 我有用户和组 每个组可以拥有以下证券 管理论坛 可以是类似的角色ROLE FORUM MANAG
  • Encog - 如何加载神经网络的训练数据

    The NeuralDataSet我在实际中看到的对象除了 XOR 之外什么都没有 它只是两个小数据数组 我无法从文档中找出任何内容MLDataSet 似乎所有内容都必须立即加载 但是 我想循环遍历训练数据 直到到达 EOF 然后将其算作
  • Lambda 表达式更慢?

    我有下面这段代码 PriorityQueue
  • java.lang.IllegalArgumentException:比较方法违反了其一般契约[重复]

    这个问题在这里已经有答案了 您好 下面是我的比较器的比较方法 我不确定出了什么问题 我在堆栈溢出上查找了其他类似标题的问题和答案 但不确定我的方法出了什么问题 但我不断收到 java lang IllegalArgumentExceptio
  • 如何将 openapi-generator 中的客户端包含在 gradle java 应用程序中?

    我想创建一个 gradle java 应用程序 它从 openAPI 规范文件生成客户端并使用该客户端 所以我创建了一个java应用程序gradle init 类型 应用程序 语言 Java DSL groovy 测试框架 Junit Ju
  • 如何在 Java 中用 \n 替换 \\n

    我有一个string test first n middle n last 现在我想更换所有 n by n 我试过了test replaceAll n n and test replaceAll n n 但它们不起作用 有人有解决办法吗 T
  • 关于java中同步的问题;何时/如何/到什么程度

    我正在开发我的第一个多线程程序 并在同步的几个方面陷入困境 我已经浏览了 oracle sun 主页上的多线程教程 以及这里的一些关于 SO 的问题 所以我相信我知道什么是同步 然而 正如我提到的 有几个方面我不太确定如何弄清楚 我以明确问
  • 正则表达式或用单个空格替换多个空格的方法

    你能告诉我有没有办法在java或spring中用单个空格替换多个空格 有相同的 stringUtils 函数吗 like 1 test test test test 2 test test test test 3 test test tes
  • 如何查找给定字符串中仅出现一次的第一个字符[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 自动检测log4j静态初始化错误的方法

    请注意 这更像是 Bash 问题 而不是 Java 问题 请参阅下面的注释 在每个类中配置log4j时 我们执行以下操作 public class Example private static final Logger log Logger
  • 如果在构造函数中使用 super 调用重写方法会发生什么

    有两个班级Super1 and Sub1 超1级 public class Super1 Super1 this printThree public void printThree System out println Print Thre
  • 是否可以从 JBoss 容器中部署的所有 .war 文件中读取属性文件

    我已成功将 war 部署到 Jboss Web 容器 其中包含并读取位于 META INF groupid dir artifactid dir 下的 pom properties 为了访问该文件 我在同一 war 中的 JSP 中使用了以
  • Java并发锁和条件的使用

    我可以用object wait object notify and synchronized blocks解决生产者消费者类型的问题 同时我可以使用locks and conditions from java util concurrent
  • 如何将模型从 ML Pipeline 保存到 S3 或 HDFS?

    我正在尝试保存 ML Pipeline 生成的数千个模型 正如答案中所示here https stackoverflow com questions 32121046 run 3000 random forest models by gro
  • SWIG C 函数指针和 JAVA

    我有一些 C 代码 其中一个方法有一个函数指针作为参数 我正在尝试在我的 Android 应用程序中使用 C 代码 我决定使用 SWIG 来完成生成我需要的 java 文件的所有工作 一切都适用于常规函数 没有函数指针作为参数的函数 但我不
  • 配置Spring的MappingJacksonHttpMessageConverter

    我在用MappingJacksonHttpMessageConverter在 Spring MVC 中自动序列化对象 如下所示 RequestMapping value getAccount method RequestMethod GET
  • 注释处理工具<-检查有效注释

    I have ColumnMetadata index 1 ColumnMetadata index 2 ColumnMetadata index 3 我必须使用 APT 检查索引号是否唯一 我不知道该怎么做 我看不懂教程 一般我在网上找资
  • 如何在 Android 上设置 Google Drive API?

    我一直在尝试将 Google Drive 功能集成到我的应用程序中 但我无法使用任何内置功能 因此我相信我要么错过了一个步骤 要么做得不正确 我正在遵循官方的 Google 开发者指南 https developers google com
  • Java:将秒转换为分钟、小时和天[重复]

    这个问题在这里已经有答案了 任务是 输出应如下所示 最好回显输入 您输入了 500 000 秒 即 5 天 18 小时 53 分钟 20 秒 5天18 53 20小时 我该怎么做呢 最容易理解和做到的方法是什么 讲师还说 没有硬编码 我不太
  • 如何在服务器上获取球衣日志?

    我正在使用球衣进行 REST WS 如何在服务器端启用球衣日志 很长的故事 我收到客户端异常 但我在 tomcat 日志中没有看到任何内容 它甚至没有到达我的方法 由于堆栈跟踪显示 toReturnValue 它确实从服务器获取了一些内容

随机推荐

  • 力扣OJ(0401-600)

    目录 404 左叶子之和 412 Fizz Buzz 416 分割等和子集 419 甲板上的战舰 421 数组中两个数的最大异或值 426 将二叉搜索树转化为排序的双向链表 429 N叉树的层序遍历 431 将 N 叉树编码为二叉树 438
  • 基于springboot的课程作业管理系统

    随着科学技术的飞速发展 社会的方方面面 各行各业都在努力与现代的先进技术接轨 通过科技手段来提高自身的优势 课程作业管理系统当然也不能排除在外 课程作业管理系统是以实际运用为开发背景 运用软件工程原理和开发方法 采用springboot框架
  • ubuntu小技巧7--ubuntu如何安装flashplayer

    ubuntu小技巧7 ubuntu如何安装flashplayer 安装Ubuntu的时候经常会用大视频播放 可是默认情况下Ubuntu并未安装flashplayer插件 导致浏览器无法播放视频 因此安装flashplayer将是一个必备技能
  • C语言打印金字塔,菱形,V形图案

    文章目录 目录 文章目录 前言 一 打印金字塔 等腰三角形 1 图案 2 代码 二 打印菱形 两个三角形拼在一起 1 图案 2 代码 三 打印V形 1 图案 2 代码 四 打印 倒着的 V 1 图案 2 代码 总结 前言 使用C语言打印图形
  • 苹果ID不能登陆:The action could not be completed. Try again

    终端输入以下命令修复 sudo mkdir p Users Shared sudo chown root wheel Users Shared sudo chmod R 1777 Users Shared
  • VTD — 智能驾驶复杂交通场景仿真工具

    德国VIRES 公司开发的复杂交通场景视景仿真工具VTD Virtual Test Drive 可应用于汽车主动安全 无人车半实物测试的实时复杂交通场景生成 含雷达 红外 摄像头等传感器成像 及汽车驾驶模拟器开发中的交通视景展示 也应用于工
  • 操作系统复习笔记 06 CPU Scheduling CPU调度

    CPU的三级调度 1 高级调度 Long term 作业调度 从外存进内存 2 低级调度 Short term 进程调度 分配处理机 3 中级调度 Medium term 对换 通过多道程序设计得到CPU的最高使用率 CPU IO脉冲周期
  • 【计算机毕业设计】家政服务平台

    家政服务平台 现代经济快节奏发展以及不断完善升级的信息化技术 让传统数据信息的管理升级为软件存储 归纳 集中处理数据信息的管理方式 本家政服务平台就是在这样的大环境下诞生 其可以帮助管理者在短时间内处理完毕庞大的数据信息 使用这种软件工具可
  • Vue打包项目,并部署到Linux服务器中(详细过程)

    一 Vue打包 1 配置vue config js文件 将publicPath改为 否则会出现静态文件找不到 从而使index html文件打开空白页的问题 2 创建config js文件 并引入index html中 创建该文件主要使为了
  • 第十三章 opengl之模型(导入3D模型)

    OpenGL 模型 导入3D模型 优化 使用3D模型 模型 使用Assimp并创建实际的加载和转换代码 Model类结构如下 class Model public 函数 Model char path loadModel path void
  • MySql导出表结构到Word文档

    工具比较简陋 因工作要求临时写的 功能单一 只为了导出mysql表结构到word文档 运行环境 jdk1 8 执行命令 java jar xxxx jar 缺点 暂时只支持导出MySQL数据库 输入数据库配置和文件导出路径后点击测试连接 点
  • 正在启动文档服务器,正在启动远程服务器

    正在启动远程服务器 内容精选 换一换 本节操作介绍云服务器新内核启动失败时如何设置使用第二内核启动 本节操作适用于CentOS EulerOS操作系统 且系统内安装至少两个内核 登录控制台 重启云服务器 单击 远程登录 在出现Booting
  • 计算机win7几位,Win7 32位与64位有什么区别 Win7系统32位和64位的区别科普篇

    Win7系统分32位和64位版本 很多人在选择32位和64位系统的时候十分纠结 原因是自己的电脑应该安装哪一种版本 那么Win7 32位与64位有什么区别 下面装机之家分享一下Win7系统32位和64位的区别科普篇 Win7系统32位和64
  • 查看apk签名,查看key签名,adb常用命令

    在使用第三方sdk时经常要求绑定签名 这里提供两种查看签名的方式 如果只是想查看一下手机上应用的签名 那么可以安装一个app直接输入包名即可查看该应用的签名 提供一个微信的签名查看apk 下载连接http download csdn net
  • 【认证证书】计算机应急响应 - 中国信息安全测评中心CISP-IRE

    计算机应急响应 中国信息安全测评中心CISP IRE 知识体系 简略图片版 详细 官方 中国信息安全测评中心 http www itsec gov cn ryzc rsqsxz 版 考核方式 公安部第三研究所CCSS R 考核方式 资料 题
  • 使用wget从Google Drive下载数据集

    许多用于训练的数据集很大 一般通过Google Drive进行分享 而出于磁盘容量和方便训练的考虑 这些数据我们一般放在服务器上 服务器没有图形界面 因此我们需要使用wget来进行下载 Google Drive的链接格式是这个样子的 htt
  • go语言教程哪里有?go 语言优秀开源项目汇总

    目录 监控系统 容器技术 PaaS工具 大数据 微服务 CI CD 数据库技术 存储技术 分布式系统 消息系统 服务器管理 安全工具 网络工具 Web工具 Web框架 区块链技术 其它 监控系统 项目 简介 OpenFalcon OpenF
  • python:转义字符和input()的用法

    1 1转义字符 1序列 表反斜杆 表单引号 表双引号 a表ASCLL响铃符 BEL b表ASCLL退格符 BS f表ASCLL进纸符 FF n表ASCLL换行符 LF N name 表Udicode数据库中的字符名 其中name时它的名字
  • python 使用 openpyxl 打开及读取 excel 表格

    python 使用 openpyxl 打开及读取 excel 表格 openpyxl简介 安装openpyxl 打开及读取表格内容 1 打开 Excel 表格并获取表格名称 2 通过 sheet 名称获取表格 3 获取表格的尺寸大小 几行几
  • Spring创建Bean实例的方式

    目录 简介 源码分析 resolveBeforeInstantiation创建Bean实例 doCreateBean创建Bean实例 Supplier创建实例 FactoryMethod创建实例 自动装配构造函数创建实例 无参构造函数创建实