1 bean定义
1.1 命名
给bean命名不是必须的,但是如果如果有其它bean需要引用该bean,那么就需要给该bean命名。当我们没有给bean命名时,Spring将自动为该bean生成一个唯一的名称。
1.1.1 id和name属性
可以通过id和name给bean命名,如果只需要给bean指定一个名称则使用id和name都可以。id和name在整个ApplicationContext
中都要求是唯一的,其中id我们只能指定一个,如果我们还需要为当前bean指定更多的名称,则可以通过name进行指定。name属性可以用来为bean指定多个名称,多个名称之间可以以逗号“,”、分号“;”或空格进行分隔。
<bean id="hello" name="hello2,hello3 hello4;hello5" class="java.lang.String">
<constructor-arg value="hello"/>
</bean>
1.1.2 alias元素指定别名
alias
元素可以为指定的名称指定一个别名。假设在我们的ApplicationContext
中拥有一个名为name1的bean,同时通过alias
元素指定了name1的别名为alias1,这样在其它需要引用名为name1的bean的地方都可以使用alias1来代替,当然继续使用name1也是可以的。这种机制是非常有效的。考虑这样一种场景,假设我们的应用有两个module,其中module1需要关联名为module1-dataSource,module2需要关联名为module2-dataSource。但实际上它们使用的都是同一个数据源,当然我们可在定义该DataSource时同时指定其名称为module1-dataSource和module2-dataSource。另一种方式是我们可以为该DataSource指定两个别名,分别为module1-dataSource和module2-dataSource。
以下是一个使用alias
元素定义别名的示例,其分别指定hello的别名为helloAlias1和helloAlias2。
<alias name="hello" alias="helloAlias1"/>
<alias name="hello" alias="helloAlias2"/>
<bean name="hello" class="java.lang.String">
<constructor-arg value="hello"/>
</bean>
1.2 class属性指定类型
在定义bean时可以通过class属性来指定当前bean对应的类型。class属性要求是对应Class类的全限定名,即需要包含包名的。如果我们需要定义的bean类型属于某个类的静态内部类,那么对应的class值应该是该内部类的二进制名称,即中间以$
符号连接。下面来看一个示例,假设我们有如下这样一个类,先需要分别定义Hello对应的bean和World对应的bean,其中Hello所在的包名为com.app
。
public class Hello {
public static class World {
}
}
那么,对应bean定义应该是这样子的:
<bean id="hello" class="com.app.Hello"/>
<bean id="world" class="com.app.Hello$World"/>
1.3 depends-on
depends-on
是定义在bean元素上的一个属性,用于指定其所依赖的bean,这样Spring将在初始化当前bean前先初始化其depends-on属性所指定的bean。所以depends-on的功能就是指定一个bean所依赖的bean,通过它来告诉Spring将优先初始化depends-on
属性指定的bean。注意,该属性只有告诉Spring该优先初始化哪个bean的功能,Spring不会因为这个属性的定义而注入对应的bean。在不使用depends-on
属性的情况下,Spring初始化bean的顺序是固定的,通常是根据bean定义的先后顺序来进行初始化。在下面的示例中,Spring将先初始化world,再初始化hello,但是其不会将world注入给hello。
<bean name="world" class="com.app.World"/>
<!-- 通过depends-on属性告诉Spring先初始化depends-on属性指定的bean,即这里的world -->
<bean id="hello" class="com.app.Hello" depends-on="world"/>
如果我们需要指定多个bean先于某个bean被初始化,我们也可以通过depends-on属性来指定,只是此时多个bean之间需要以逗号、分号或空格进行分隔。如下示例中就表示bean1依赖于bean2、bean3和bean4,即bean2、bean3和bean4需先于bean1被初始化。
<!-- 当依赖于多个bean时,多个bean之间以逗号、分号或空格进行分隔 -->
<bean id="bean1" class="com.app.Bean1" depends-on="bean2,bean3,bean4"/>
使用depends-on
属性后,depends-on属性指定的bean将先于该bean被初始化,但对于销毁而言,其是一个逆过程,即将先销毁该bean,再销毁depends-on
属性指定的bean。
1.4 lazy-init
默认情况下,Spring将在初始化bean容器的时候初始化所有的单例bean。如果我们有一个bean是单例的,但是又不想其在bean容器初始化的时候被初始化,那么我们可以在该bean上定义lazy-init
属性为true,这样Spring将不会在初始化bean容器的时候将其初始化。相对应的,其会在第一次被需要的时候进行初始化。所以如果我们有一个叫beanA的单例bean定义了lazy-init
为true,这就表示其不会在Spring初始化bean容器的时候进行初始化,但是如果其被另一个名叫beanB的单例bean所依赖,而beanB没有指定lazy-init
为true,这就意味着beanB将在Spring初始化bean容器时进行初始化,这个时候由于Spring需要给beanB注入一个beanA,也就是说beanA在这个时候被需要了,所以此时Spring也将会初始化beanA。
<!-- 通过lazy-init="true"指定其将不在初始化bean容器时初始化 -->
<bean id="beanA" class="com.app.BeanA" lazy-init="true"/>
<!-- 由于beanB对beanA有依赖,所以在初始化BeanB后,如果容器中不存在beanA,Spring将初始化备案A -->
<bean id="beanB" class="com.app.BeanB">
<property name="beanA" ref="beanA"/>
</bean>
lazy-init
的值默认是false,也就是说对于单例bean而言,如果没有指定lazy-init=”true”
时其默认会在bean容器初始化时被初始化,如果用户希望这种全局的初始化策略为不在bean容器初始化时进行初始化,则可以在beans元素上定义default-lazy-init=”true”
。
1.5 继承bean定义(parent)
试想一下,假设我们有一个类ParentA,其需要引用BeanA、BeanB和BeanC这三种类型的对象。然后针对于ParentA而言,我们又拥有三个子类ChildA、ChildB和ChildC。如果我们现在要定义ChildA、ChildB和ChildC三种类型的bean,依据传统的思想是不是就需要定义这三个bean,然后分别给这三个bean注入类型为BeanA、BeanB和BeanC的bean呢?Spring为我们提供了一种继承机制,它允许我们在定义一个bean时指定其对应的父bean,然后子bean将继承父bean的属性等,当然通过子bean注入的内容将覆盖父bean的内容,这里所谓的继承是对应bean定义的继承,不是真正意义上对象的继承。Spring允许我们在定义一个bean时通过parent属性来指定对应的父bean定义,其属性值对应父bean的id或name。所以针对于该应用场景,我们可以使用Spring的继承机制进行如下定义。
<?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="beanA" class="com.app.BeanA"/>
<bean id="beanB" class="com.app.BeanB"/>
<bean id="beanC" class="com.app.BeanC"/>
<bean id="parentA" class="com.app.ParentA">
<property name="beanA" ref="beanA"/>
<property name="beanB" ref="beanB"/>
<property name="beanC" ref="beanC"/>
</bean>
<bean id="childA" class="com.app.ChildA" parent="parentA"/>
<bean id="childB" class="com.app.ChildB" parent="parentA"/>
<bean id="childC" class="com.app.ChildC" parent="parentA"/>
</beans>
这时子bean也可以注入自己额外的内容,比如对于childA而言,它可以给自己注入一个beanD,这是没有问题的。当然,它也可以选择给自己注入一个特定的BeanA,此时childA自己注入的BeanA将覆盖其父bean持有的BeanA,即childA所拥有的BeanA将是其自身注入的那一个。
对于上述配置而言,将默认初始化所有的单例bean,所以上述配置中的parentA也将被初始化,如果我们不希望其被初始化,或者parentA是一个抽象类,根本就不能被初始化,我们可以在该bean上通过abstract=”true”指定该bean是抽象的,这样Spring将不会对其进行初始化,而仅仅把它当做其它bean定义的父bean定义而已。
<bean id="parentA" class="com.app.ParentA" abstract="true">
<property name="beanA" ref="beanA"/>
<property name="beanB" ref="beanB"/>
<property name="beanC" ref="beanC"/>
</bean>
如果我们的父bean不需要真正被初始化,只是用来作为一个父bean
定义供子bean
继承时,我们也可以不指定其对应的class
,但需要指定abstract=”true”
。这对实际应用是非常有用的,打个比方,如果我们的应用是通过XML
配置来管理对应的依赖关系的,同时我们的Dao都需要注入一个JdbcTemplate
,我们就无需在定义Dao对应bean
时给每个bean都定义注入一个JdbcTemplate
,而可以让它们都继承一个父级的bean
定义,然后在父级的bean
定义上去注入对应的JdbcTemplate
。如:
<bean id="parent" abstract="true">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="xxxDao" class="xxx.xxx.xxxDao" parent="parent"/>
1.6 description
通过description
元素指定当前bean
的描述信息,方便用户阅读。
<bean id="hello" class="com.app.Hello">
<description>当前bean的描述信息,便于阅读</description>
</bean>
(注:本文是基于Spring4.1.0所写)
相关推荐
在Spring框架中,通常会把应用程序对象定义在XML配置文件中,Spring IoC容器会解析这些XML文件,并根据文件中定义的bean的配置信息来创建和管理这些对象。举例来说,使用ClassPathXmlApplicationContext可以从...
在本篇【框架源码篇 04】中,我们将深入探讨Spring框架的核心概念——Bean定义配置化。Spring是Java领域最广泛使用的依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect-Oriented Programming,简称...
本文将深入探讨“Spring AOP——Schema”,这是Spring AOP的一种配置方式,通过XML schema定义切面和通知。 首先,我们需要理解AOP的基本概念。面向切面编程是一种编程范式,旨在提高软件的模块化程度,将关注点...
在"Quartz Spring整合——附带webservice Demo"的项目中,我们可以看到如何将这两个强大的工具结合在一起。这个Demo可能包含了一个使用Quartz调度器来触发Web服务调用的示例。Web服务(Webservice)是一种基于标准的...
《Spring源码分析——BeanFactory》 在Java的IoC(Inversion of Control)和DI(Dependency Injection)领域,Spring框架扮演着至关重要的角色。BeanFactory是Spring的核心组件之一,它是容器的基石,负责管理应用...
现在,如果项目中有任何bean实现了`SomeInterface`,它们都将自动拥有`SomeService`的实例,而无需显式地在bean定义中声明。这使得我们可以为项目中的多个类添加统一的行为,而无需修改它们的源代码。 需要注意的是...
本篇文章将深入探讨Spring框架的一个重要特性——事件驱动模型。通过理解这一特性,开发者可以更好地利用Spring来实现应用间的通信和协调,提高系统的灵活性和可扩展性。 事件驱动模型是一种设计模式,它基于发布/...
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> </bean> <!-- SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring...
此外,通过两个具体的案例——HelloWorld案例和报销单维护案例,我们更加深入地理解了SpringBean的实际应用场景及其带来的价值。 最后,如果在开发过程中遇到任何问题,可以通过官方网站([www.primeton.com]...
首先,我们需要了解 Spring 的核心概念——Bean。在 Spring 中,Bean 是由 Spring 容器管理的对象,它们可以通过 XML 配置文件进行定义。例如,一个简单的 Bean 定义可能如下: ```xml <bean id="exampleBean" ...
除了基本的`@Component`家族,Spring还提供了一些高级注解,如`@Scope`用于定义Bean的作用域,`@Lazy`用于延迟初始化Bean,`@Qualifier`用于在多个相同类型的Bean中指定特定的一个。 ### **总结** Spring的自动...
《Spring源码分析——ApplicationContext》 在Java世界中,Spring框架是不可或缺的一部分,它以其强大的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)特性,极大地...
这些素材可能会讲解如何配置Spring容器,如何编写Bean定义,如何使用注解进行编程,或者如何实现AOP切面,甚至可能涉及到Spring与其他技术的集成,比如数据库连接、RESTful服务等。 在Spring框架中,依赖注入是核心...
1. **ApplicationContext**:这是Spring提供的一个接口,代表了Spring的上下文,包含了bean的定义和bean的实例。我们可以使用`ApplicationContext`来获取bean。例如: ```java ApplicationContext context = new ...
在Spring配置文件中,我们需要定义一个工厂bean,然后指定该工厂bean的`factory-bean`属性,以及工厂bean中用于创建目标bean的方法,即`factory-method`属性。下面是一个简单的例子: ```xml <bean id="myFactory...
在Spring框架中,Bean的作用域是管理Bean实例生命周期的关键概念,它决定了Bean如何在应用程序中创建、使用和销毁。Bean的作用域主要有四种:Singleton、Prototype、Request和Session,每种都有其特定的适用场景和...
Spring-beans模块负责Bean的定义,类的实例化,以及依赖关系的处理;Spring-context模块提供了访问应用程序对象的上下文,它是一个配置文件,用于配置应用程序中的对象,它还集成了Spring AOP的功能;Spring-context...