spring之BeanFactory

本文介绍Spring框架中的IOC容器原理,并通过模拟实现展示了如何通过BeanFactory接口及其实现类ClassPathXmlApplicationContext来实例化、配置和管理对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring的IOC容器能够帮我们自动new对象,对象交给spring管之后我们不用自己手动去new对象了。那么它的原理是什么呢?是怎么实现的呢?下面我来简单的模拟一下spring的机制,相信看完之后就会对spring的原理有一定的了解。

  spring使用BeanFactory来实例化、配置和管理对象,但是它只是一个接口,里面有一个getBean()方法。我们一般都不直接用BeanFactory,而是用它的实现类ApplicationContext,这个类会自动解析我们配置的applicationContext.xml,然后根据我们配置的bean来new对象,将new好的对象放进一个Map中,键就是我们bean的id,值就是new的对象。

  首先我们建立一个BeanFactory接口

1 package com.spring;
2 
3 public interface BeanFactory {
4     Object getBean(String id);
5 }

  然后建立一个BeanFactory的实现类ClassPathXmlApplicationContext.java

复制代码
 1 package com.spring;
 2 
 3 import java.util.HashMap;
 4 import java.util.List;
 5 import java.util.Map;
 6 
 7 import org.dom4j.Document;
 8 import org.dom4j.DocumentException;
 9 import org.dom4j.Element;
10 import org.dom4j.io.SAXReader;
11 
12 
13 public class ClassPathXmlApplicationContext implements BeanFactory {
14     private Map<String, Object> beans = new HashMap<String, Object>();
15     public ClassPathXmlApplicationContext(String fileName) throws Exception{
16         SAXReader reader = new SAXReader();
17         Document document = reader.read(this.getClass().getClassLoader().getResourceAsStream(fileName));
18         List<Element> elements = document.selectNodes("/beans/bean");
19         for (Element e : elements) {
20             String id = e.attributeValue("id");
21             String value = e.attributeValue("class");
22             Object o = Class.forName(value).newInstance();
23             beans.put(id, o);
24         }
25     }
26     
27     public Object getBean(String id) {
28         return beans.get(id);
29     }
30 
31 }
复制代码

  然后配置applicationContext.xml

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans>
3     <bean id="c" class="com.spring.Car"></bean>
4      <bean id="p" class="com.spring.Plane"></bean>
5 </beans>

创建类的时候顺便演示一下工厂模式,其实BeanFactory它也是一种工厂模式的。

1 package com.spring;
2 
3 public interface Moveable {
4     void run();
5 }
复制代码
1 package com.spring;
2 
3 public class Car implements Moveable{
4     
5     public void run(){
6         System.out.println("拖着四个轮子满街跑car·····");
7     }
8 }
复制代码
复制代码
1 package com.spring;
2 
3 public class Plane implements Moveable{
4 
5     public void run() {
6         System.out.println("拖着翅膀天空飞plane......");
7     }
8     
9 }
复制代码

 

现在来看一看效果吧,写一个类测试一下:

复制代码
 1 package com.spring;
 2 
 3 import org.dom4j.DocumentException;
 4 
 5 public class Test {
 6 
 7     /**
 8      * @param args
 9      * @throws DocumentException 
10      */
11     public static void main(String[] args) throws Exception {
12         BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
13         Object o = factory.getBean("c");
14         Moveable m = (Moveable)o;
15         m.run();
16     }
17 
18 }
复制代码

由于Map容器里面保存的是Object类型,所以通过getBean()方法取出来的对象要强制类型转换。

 

### Spring 框架中 BeanFactory 的使用方法 #### 基本概念 `BeanFactory` 是 Spring 框架的核心接口之一,它作为 IoC (控制反转) 容器的基础实现,主要用于实例化、配置和管理 Bean 的生命周期[^1]。通过 `BeanFactory`,开发者能够按需加载并获取所需的 Bean。 #### 特性概述 `BeanFactory` 支持延迟加载机制,在实际调用 `getBean()` 方法之前不会初始化任何未使用的 Bean[^5]。这种特性使得资源消耗较低,但在某些情况下可能导致潜在的错误被推迟发现。 当一个类实现了 `org.springframework.beans.factory.BeanFactoryAware` 接口时,Spring 容器会在适当的时候自动回调该类的 `setBeanFactory(BeanFactory)` 方法,从而将当前的 `BeanFactory` 实例传递给这个对象[^2]。 以下是基于 XML 配置文件的一个典型例子来演示如何使用 `BeanFactory`: #### 示例代码 假设我们有一个简单的 Java 类如下所示: ```java public class HelloWorld { private String message; public void setMessage(String message){ this.message = message; } public void getMessage(){ System.out.println("Message : " + message); } } ``` 接着定义对应的 XML 文件 (`beans.xml`) 来描述上述类以及其依赖关系: ```xml <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"> <!-- Definition for helloWorld bean --> <bean id="helloWorld" class="com.example.HelloWorld"> <property name="message" value="Hello World!"/> </bean> </beans> ``` 最后编写测试程序以验证 `BeanFactory` 是否能正常工作: ```java import org.springframework.context.support.ClassPathXmlApplicationContext; import com.example.HelloWorld; public class MainApp { public static void main(String[] args) { try { // 创建 BeanFactory 对象 var factory = new ClassPathXmlApplicationContext("beans.xml"); // 获取名为 'helloWorld' 的 Bean HelloWorld obj = (HelloWorld)factory.getBean("helloWorld"); // 调用业务逻辑 obj.getMessage(); } catch(Exception e){ e.printStackTrace(); } } } ``` 注意这里虽然直接用了更高层次的应用上下文 API(`ClassPathXmlApplicationContext`),但实际上内部仍然会利用到低级别的 `BeanFactory` 功能[^4]。 #### 扩展功能 对于更复杂的场景需求,比如批量查询所有的 Beans 或者按照特定条件筛选 Beans,则可以考虑继承自 `BeanFactory` 的其他高级接口如 `ListableBeanFactory` 提供的功能支持[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值