Spring(01)——bean定义

简介: 1 bean定义 1.1 命名 给bean命名不是必须的,但是如果如果有其它bean需要引用该bean,那么就需要给该bean命名。当我们没有给bean命名时,Spring将自动为该bean生成一个唯一的名称。

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所写)

 

目录
相关文章
|
18天前
|
XML 安全 Java
|
1天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
15 6
|
2天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
28 3
|
4月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
16天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
27 1
|
2月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
80 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
3月前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
312 24
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
2月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
3月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
246 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
下一篇
DataWorks