容器和bean的基本原理

org.springframework.beans及org.springframework.context包是Spring IoC容器的基础。
BeanFactory提供的高级配置机制,使得管理任何性质的对象成为可能。
简介
ApplicationContext是BeanFactory的扩展,功能得到了进一步增强,比如更易与Spring AOP集成、消息资源处理(国际化处理)、事件传递及各种不同应用层的context实现(如针对web应用的WebApplicationContext)。

容器
在Spring中,BeanFactory是IoC容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

Spring为我们提供了许多易用的BeanFactory实现,XmlBeanFactory就是最常用的一个。该实现将以XML方式描述组成应用的对象以及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个完全可配置的系统或应用。

配置元数据
到目前为止,基于XML的元数据是最常用到的配置元数据格式。然而,它并不是唯一的描述格式。Spring IoC容器在这一点上是完全开放的。

bean定义与应用程序中实际使用的对象一一对应。通常情况下bean的定义包括:服务层对象、数据访问层对象(DAO)、类似Struts Action的表示层对象、Hibernate SessionFactory对象、JMS Queue对象等等。项目的复杂程度将决定bean定义的多寡。

实例化容器
Spring IoC容器的实例化非常简单,如下面的例子:
Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);

ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);

ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
// of course, an ApplicationContext is just a BeanFactory
BeanFactory factory = (BeanFactory) context;

组成基于XML配置元数据
为了加载多个XML文件生成一个ApplicationContext实例,可以将文件路径作为字符串数组传给ApplicationContext构造器。
另外一种方法是使用一个或多个的<import/>元素来从另外一个或多个文件加载bean定义。
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
正如你所看到的那样,开头的斜杠‘/’实际上可忽略。因此不用斜杠‘/’可能会更好一点。根据Spring XML配置文件的Schema(或DTD),被导入文件必须是完全有效的XML bean定义文件,且根节点必须为<beans/> 元素。

命名bean
每个bean都有一个或多个id(或称之为标识符或名称,在术语上可以理解成一回事)。这些id在当前IoC容器中必须唯一。如果一个bean有多个id,那么其他的id在本质上将被认为是别名。通常情况下最好为bean指定一个id。尽管XML规范规定了XML ID命名的有效字符,但是bean标识符的定义不受该限制。

在对bean进行定义时,除了使用id属性来指定名称之外,为了提供多个名称,需要通过alias属性来加以指定。而所有的这些名称都指向同一个bean,在某些情况下提供别名非常有用,比如为了让应用的每一个组件能更容易的对公共组件进行引用。在XML配置文件中,可用单独的<alias/> 元素来完成bean别名的定义。
<alias name="fromName" alias="toName"/>

实例化bean
当需要的时候,容器会从bean定义列表中取得一个指定的bean定义,并根据bean定义里面的配置元数据使用反射机制来创建一个实际的对象。
当采用XML描述配置元数据时,将通过<bean/>元素的class属性来指定实例化对象的类型。

class属性主要有两种用途:在大多数情况下,容器将直接通过反射调用指定类的构造器来创建bean(这有点等类似于在Java代码中使用new操作符);在极少数情况下,容器将调用类的静态工厂方法来创建bean实例,class属性将用来指定实际具有静态工厂方法的类(至于调用静态工厂方法创建的对象类型是当前class还是其他的class则无关紧要)。

1.用构造器来实例化
当采用构造器来创建bean实例时,根据所采用的IoC类型,class可能需要一个默认的空构造器。

此外,IoC容器不仅限于管理JavaBean,它可以管理任意的类。不过大多数使用Spring的人喜欢使用实际的JavaBean(具有默认的(无参)构造器及setter和getter方法),但在容器中使用非bean形式(non-bean style)的类也是可以的。比如遗留系统中的连接池,很显然它与JavaBean规范不符,但Spring也能管理它。

当使用基于XML的元数据配置文件,可以这样来指定bean类:
<bean id="exampleBean" class="examples.ExampleBean"/>

2.使用 静态工厂方法实例化
当采用静态工厂方法创建bean时,除了需要指定class属性外,还需要通过factory-method属性来指定创建bean实例的工厂方法。Spring将调用此方法(其可选参数接下来介绍)返回实例对象。

下面的bean定义展示了如何通过工厂方法来创建bean实例。注意,此定义并未指定返回对象的类型,仅指定该类包含的工厂方法。在此例中, createInstance()必须是一个static方法。
<bean id="exampleBean"
class="examples.ExampleBean2"
factory-method="createInstance"/>

3.使用实例工厂方法实例化
与使用静态工厂方法实例化类似,用来进行实例化的实例工厂方法位于另外一个已有的bean中,容器将调用该bean的工厂方法来创建一个新的bean实例。

为使用此机制,class属性必须为空,而factory-bean属性必须指定为当前(或其祖先)容器中包含工厂方法的bean的名称,而该工厂bean的工厂方法本身必须通过factory-method属性来设定(参看以下的例子)。

<!-- the factory bean, which contains a method called createInstance() -->
<bean id="myFactoryBean" class="...">
...
</bean>
<!-- the bean to be created via the factory bean -->
<bean id="exampleBean"
factory-bean="myFactoryBean"
factory-method="createInstance"/>

使用容器
从本质上讲,BeanFactory仅仅只是一个维护bean定义以及相互依赖关系的高级工厂接口。通过BeanFactory我们可以访问bean定义。
InputStream is = new FileInputStream("beans.xml");
BeanFactory factory = new XmlBeanFactory(is);
接着使用getBean(String)方法就可以取得bean的实例。

BeanFactory提供的方法:
boolean containsBean(String):如果BeanFactory包含给定名称的bean定义(或bean实例),则返回true。
Object getBean(String):返回以给定名字注册的bean实例。根据bean的配置情况,如果为singleton模式将返回一个共享的实例,否则将返回一个新建的实例。
Object getBean(String, Class):返回以给定名称注册的bean实例,并转换为给定class类型的实例。
Class getType(String name):返回给定名称的bean的Class。
boolean isSingleton(String):判断给定名称的bean定义(或bean实例)是否为singleton模式。
String[] getAliases(String):返回给定bean名称的所有别名。
### Spring IOC 容器工作原理 Spring IOC(Inversion of Control,控制反转)容器的核心功能是对应用程序中的组件(即Bean)进行管理配置。它通过依赖注入(Dependency Injection, DI)的方式减少硬编码耦合度,从而提高系统的可维护性扩展性。 #### 创建过程 Spring框架内部使用`DefaultListableBeanFactory`作为唯一的`BeanFactory`实现类[^2]。该类负责加载并管理所有的Bean定义,并提供获取Bean实例的功能。此外,在实际开发中通常会结合`ApplicationContext`接口一起使用,后者不仅提供了基本的`BeanFactory`功能,还增加了事件发布、国际化支持等功能。 --- ### Bean 的生命周期管理机制 在Spring IOC容器中,Bean的生命周期由一系列阶段组成,这些阶段包括但不限于创建、初始化销毁三个主要部分: 1. **实例化** - 通过构造函数或者工厂方法完成Bean对象的创建。 2. **属性赋值** - 使用反射技术调用Setter方法为Bean注入所需的依赖项其他参数。 3. **初始化前处理** - 如果存在自定义逻辑,则在此期间执行;例如可以通过`@PostConstruct`注解标记的方法自动运行一次[^1]。 4. **调用后置处理器(PostProcessor)** - `BeanPostProcessor`接口允许开发者介入到每一个被托管的对象上做进一步操作比如验证某些字段是否合法等等[^3]。注意这里强调的是作用于整个上下文中所有符合条件的目标而不是单独针对某一个个体。 5. **初始化完成后回调** - 用户可通过设置`init-method`属性指定某个特定函数名作为启动后的入口点。 6. **正常服务状态** 此时bean已经准备好接受外部请求直到系统决定将其移除为止。 7. **销毁准备活动** 当不再需要此资源时(如关闭web服务器),spring将会按照预先设定好的规则清理现场——也就是触发对应的destroy钩子函数。 8. **最终释放内存空间** 以下是基于上述理论的一个简单例子展示如何利用java代码配合xml文件共同构建起这样一个流程: ```xml <bean id="exampleBean" class="com.example.ExampleBean" init-method="initialize" destroy-method="cleanup"/> ``` ```java public class ExampleBean { public void initialize() { System.out.println("Initializing bean..."); } public void cleanup() { System.out.println("Destroying bean..."); } } ``` 以上片段展示了怎样显式地告诉spring framework何时何地应该去触发生命周期内的各个重要时刻点. --- ### 总结 综上所述,Spring IOC容器不仅仅是一个简单的工厂模式实现者而已;相反地,它是围绕着面向切面编程(AOP),事务管理(TM),消息传递(Messaging)等诸多领域展开的强大工具集之一成员.Similarly managing beans within such environment involves more than just instantiating objects but also ensuring they follow well-defined lifecycle stages from birth through death inclusive all necessary intermediate steps along the way.[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值