网站首页 > 技术文章 正文
《Spring6》第03节:简单介绍Spring创建Bean对象的原理
前面介绍了如何搭建Spring6.x框架的基础开发环境,并且通过几行代码就可以获取到Bean对象,可以看到,我们没有主动通过new关键字创建对象,而是直接调用Spring提供的getBean()方法就获取到了相应的对象。
我猜你可能有疑问,Java里面创建对象不是要使用new关键字吗?为什么在Spring里面没有使用new关键字也可以获取到对象呢?下面我就给你们解答一下这个疑问。
1.1、反射机制
我们在刚学习Java语言的时候,都知道创建对象需要使用new关键字,例如:
- 创建一个对象,就需要写出下面的代码。
AService aService = new AService();
- 后面我们又学习了Java中的反射机制,从而又解锁了一种新的创建对象的方式,即:采用反射机制创建对象。
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 1、加载类对象
Class<?> clazz = Class.forName("com.spring.study.AService");
// 2、创建实例对象
AService aService = (AService) clazz.newInstance();
// 3、调用类中方法
aService.demo01();
}
}
看到这里,你是不是有一点懂了Spring是如何通过XML配置文件创建对象的啦。没错,Spring就是利用的Java反射机制,根据XML配置中的类路径信息,获取到相应的类对象,然后利用无参构造方法实例化对象。这里我们就可以将Spring创建对象的步骤,大致理解成下面三个:
- 第一步:读取XML配置信息。
- 第二步:利用Java反射机制和工厂模式,根据读取到的类路径信息,实例化对象。
- 第三步:通过getBean()方法,获取Bean对象。
下面我们就简单的实现一下Spring创建Bean对象的过程,加深Spring创建Bean的原理的理解,当然,这里只是简单的实现Spring创建并且获取Bean对象的代码,Spring的源码中肯定没有这篇文章写的这么简单的啦。
1.2、读取XML配置
这里采用dom4j来读取XML配置信息,首先引入dom4j的依赖:
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
接着编写一个XmlReaderUtil工具类,读取src/main/resources目录下的demo.xml配置文件,将其中配置信息保存到Map容器里面。
package com.spring.study.ioc;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.util.ResourceUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author ZhuYouBin
* @version 1.0.0
* @date 2024/8/20 11:46
* @description
*/
public class XmlReaderUtil {
public static Map<String, String> getBeanDefinitionMap() {
Map<String, String> beanMap = new HashMap<>();
try {
// 创建 SAXReader 对象
SAXReader reader = new SAXReader();
// 读取 resources 目录下的 XML 文件
Document document = reader.read(ResourceUtils.getFile("classpath:demo.xml"));
// 获取根元素
Element root = document.getRootElement();
// 遍历根元素下的子元素
List<Element> childElements = root.elements();
for (Element element : childElements) {
// 获取bean节点的id和class属性
String id = element.attribute("id").getText();
String aClass = element.attribute("class").getText();
beanMap.put(id, aClass);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return beanMap;
}
}
1.3、创建工厂类
创建一个BeanFactory工厂类,其中定义一个getBean()方法,用于根据指定bean名称获取对象。
package com.spring.study.ioc;
import java.util.HashMap;
import java.util.Map;
/**
* @author ZhuYouBin
* @version 1.0.0
* @date 2024/8/20 11:30
* @description
*/
public class BeanFactory {
private static final Map<String, Object> BEAN_MAP = new HashMap<>();
static {
Map<String, String> definitionMap = XmlReaderUtil.getBeanDefinitionMap();
definitionMap.forEach((name, className) -> {
try {
// 利用反射机制创建bean
Class<?> clazz = Class.forName(className);
Object bean = clazz.newInstance();
BEAN_MAP.put(name, bean);
} catch (Exception e) {
e.printStackTrace();
}
});
}
public static <T> T getBean(String name) {
return (T) BEAN_MAP.get(name);
}
}
1.4、编写测试类
创建TestCode测试类,使用BeanFactory工厂类中的getBean()方法就可以获取到指定的Bean对象了。
package com.spring.study.ioc;
import com.spring.study.AService;
/**
* @author ZhuYouBin
* @version 1.0.0
* @date 2024/8/20 11:50
* @description 测试代码
*/
public class TestCode {
public static void main(String[] args) {
// 1、获取bean
AService aService = BeanFactory.getBean("aService");
// 2、使用bean
aService.demo01();
}
}
运行结果如下所示:
1.5、源代码获取
源代码地址:
https://gitcode.com/knowledge-base/spring-study/tree/spring6-chapter-03
到此,Spring创建Bean对象以及获取Bean对象的大致过程就简单介绍完了,通过这篇文章是不是对Spring更加熟悉了一点点呢。
今天就到这里,未完待续~~
猜你喜欢
- 2024-09-22 MyBatis模拟实现
- 2024-09-22 成都校区*精品*Dom4J解析XML的范例浅析
- 2024-09-22 Jenkins Nested View插件XXE漏洞(CVE-2021-21680)分析
- 2024-09-22 Java互联网架构-Spring IOC底层源码分析
- 2024-09-22 XML文件
- 2024-09-22 Dom4j解析xml的小demo
- 2024-09-22 java全栈CMS:AOP+Freemarke代码自动生成4
- 2024-09-22 专科生逆袭入职阿里P6,成人生赢家。网友:我应该也可以
- 2024-09-22 在IDEA的maven项目中连接使用MySQL8.0方法教程
- 2024-09-22 Spring:IOC 控制反转
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)