Bean配置概述
配置文件
Spring 的配置文件是用于指导 Spring 工厂进行 Bean 的生产、依赖关系注入及 Bean 实例分发的“图纸”,是Spring的基础。如果我们没有配置文件的话,则Spring的容器将无从谈起。
它是一个或多个标准的XML文档,其ApplicationContext.xml是Spring的默认配置文件,当容器启动时找不到其他的配置文件时,则会尝试加载这个默认的配置文件。
Spring容器成功启动需要以下三方面的条件同时具备:
- Spring的类包必须已经放在Spring的类容器下面
- 应用程序应当为Spring提供完备的Bean的配置信息
- Bean的类都已经放在Spring的类容器下面
Spring启动时读取应用程序提供的Bean的配置信息,并在Spring容器中生成一份相应的Bean的配置注册表,然后根据这张注册表来实例化Bean,装配好Bean之间的依赖关系,为上层应用提供准备就绪的运行环境。
而bean的配置信息就是Bean的元数据信息,他由以下五个方面来组成:
- Bean的实现类
- Bean的属性信息 比如:数据源的连接数,用户名和密码等等。
- Bean的依赖关系 Spring根据依赖关系配置完成Bean之间的装配
- Bean的行为配置 比如:生命周期范围以及生命周期各个过程的回调函数等
- Bean的创建方式定义 主要说明是通过构造器还是工厂方法来构造Bean
基础的Bean操作示例
最基础的bean配置如下:
1 | <bean id="bean_test" class="cn.qtone.test.HelloWorld"></bean> |
这是最基础的 Bean
配置,使用了默认的构造方法来实例化HelloWorld
类。相当于在
Java 代码中使用new HelloWorld()
来创建对象。
获取 Bean 实例
1 | // 1.创建Spring IOC容器对象,ApplicationContext表示容器,是一个接口,ClassPathXmlApplicationContext是ApplicationContext的一个实现类 |
这里首先创建了一个ClassPathXmlApplicationContext
对象,它会加载指定的配置文件applicationContext.xml
。然后通过getBean
方法,根据
Bean 的 id 获取对应的实例
默认情况下,Spring 中的 Bean
是单例的,在spring配置中的整个应用期间只有一个实例,当然这个单例是指对一个IOC容器(spring)来说的,当然,spring也可以这样配置不是单态的实例,比如可以通过scope
属性来修改
Bean 的作用域
1 | <bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype"></bean> |
将scope
设置为prototype
后,每次从 Spring
容器中获取HelloWorld
的实例时,都会创建一个新的对象,即我们所说的原型。spring
中 scope 默认的是单态(singleton),除了prototype
,Spring
还支持其他作用域,如request
、session
等,具体使用哪种作用域取决于应用程序的需求
如果HelloWorld
类没有空的构造方法,而是有带参数的构造方法,如下所示
1 | public HelloWorld(String str) |
那么在配置 Bean
时需要指定构造参数,使用<constructor-arg>
标签来指定构造函数的参数值,可以按照参数的顺序依次配置:
1 | <bean id="bean_date" class="java.util.Date" /> |
在这个例子中,第一个参数是通过ref
引用了另一个配置好的
Bean(bean_date
),第二个参数是直接指定了一个整数值。
当然,这样对简单的构造来说不会有什么问题,如果情况比较复杂的话,那么一般建议使用序号来标定,如下:
1 | <!-- 使用二个参数的构造 --> |
Bean的配置框架
- 配置形式
- 基于 xml 文件
- 基于注解
- 基于特定的 Java 类提供 Bean 定义信息
- 配置方式
- 通过全类名(反射)
- 通过工厂方法(静态工厂方法、实例工厂方法)
- FactoryBean
- 依赖注入方式
- 属性注入
- 构造器注入
Bean的基础配置
在Spring中,Bean的基础配置主要通过XML文件定义,核心元素包括:
<bean>
标签:定义Bean的基本信息。id
属性:Bean的唯一标识符,用于在容器中查找Bean。class
属性:Bean的全限定类名(包名+类名),Spring通过反射实例化该类。scope
属性:定义Bean的作用域(如singleton
、prototype
等),默认是单例模式。
Bean基础配置
在 Spring 框架中,Bean 是由 Spring IOC 容器管理的对象。通过 XML 配置文件或注解,可以定义 Bean 的创建方式、依赖关系和生命周期。
1 | <bean id="beanName" class="com.example.MyClass"></bean> |
- id:Bean 的唯一标识符,用于从容器中获取实例。
- class:Bean 的全限定类名,指定要实例化的 Java 类。

在Spring容器的配置文件中定义一个简要Bean的配置片段如下所示:

一般情况下,Spring
IOC容器中的一个Bean即对应配置文件中的一个<bean>
,这种镜像对应关系应该容易理解。其中id
为这个Bean的名称,通过容器的getBean("foo")
即可获取对应的Bean,在容器中起到定位查找的作用,是外部程序和Spring
IOC容器进行交互的桥梁。class
属性指定了Bean对应的实现类。
Bean别名配置
在实际开发中,一个 Bean 可能需要多个名称(别名),方便在不同场景下引用。Spring 提供了两种方式配置别名:
使用
<alias>
标签1
2
3<bean id="userService" class="com.example.service.UserServiceImpl"></bean>
<alias name="userService" alias="service1" />
<alias name="userService" alias="service2" />- name:原 Bean 的 id 或名称。
- alias:新的别名。
在
<bean>
标签内使用name
属性1
2
3
4<bean id="userService"
name="service1, service2, service3"
class="com.example.service.UserServiceImpl">
</bean>- name:可以指定多个别名,用逗号、空格或分号分隔。
Bean作用范围配置
Bean 的作用域决定了 Spring 如何创建和管理 Bean
实例。通过scope
属性可以指定 Bean 的作用域类型:
1 | package com.example; |
1 |
|
运行AppForScope
类的main
方法后,在控制台会看到类似如下输出:
1 | com.example.dao.BookDaoImpl@12345678 |
这表明两次从 Spring
容器中获取的bookDao
实例是同一个对象,这就验证了在 Spring
中,当不指定scope
属性时,Bean
的默认作用域是单例,即整个应用中只有一个该 Bean
的实例,多次获取得到的都是同一个实例。
为什么 Bean 默认为单例?
- 其实很简单,如果对象不复用,就是 Spring 的 Bean 容器压力就很容易很大
单例模式:默认
1 | <bean id="userService" class="com.example.service.UserServiceImpl" scope="singleton"> |
- 特性:每个 Spring 容器中只创建一个实例,所有请求共享该实例。
- 适用场景:无状态的服务类、工具类等(如
DAO、Service)。
- 单例 Bean
如果包含可变状态(如成员变量),可能存在线程安全问题。推荐单例 Bean
设计为无状态对象(如 Service
层,DAO层),有状态对象使用
prototype
作用域。
- 单例 Bean
如果包含可变状态(如成员变量),可能存在线程安全问题。推荐单例 Bean
设计为无状态对象(如 Service
层,DAO层),有状态对象使用
原型模式(Prototype)
1 | <bean id="user" class="com.example.entity.User" scope="prototype"> |
- 特性:每次请求都创建新的实例(类似
new User()
)。 - 适用场景:有状态的对象(如实体类、需要保存会话数据的类)。
Web 环境下的作用域(需 WebApplicationContext 支持)
1 | <!-- 每个HTTP请求创建一个实例 --> |
- request:每个 HTTP 请求独享一个实例。
- session:每个用户会话(Session)独享一个实例。
- application:整个 Web 应用共享一个实例(类似 ServletContext)。
使用自定义作用域(如线程作用域)
1 | <bean id="threadScopeBean" class="com.example.ThreadScopeBean" scope="thread"> |
- thread:每个线程独享一个实例。
- 需额外配置:注册自定义作用域处理器(如
SimpleThreadScope
)。
Bean基于注解的配置
我们知道,Spring容器成功启动的三大要件分别是:Bean定义信息、Bean实现类以及Spring本身。如果采用基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现。
下面是使用注解定义一个DAO的Bean
1 | package com.baobaotao.anno; |
我们使用@Component
注解在UserDao类声明处对类进行标注,它可以被Spring容器识别,Spring容器自动将POJO转换为容器管理的Bean。它和以下的XML配置是等效的:
1 | <bean id="userDao" class="com.baobaotao.anno.UserDao"/> |
组件扫描与自动装配
Spring 通过组件扫描(Component Scanning)自动发现应用中定义的 Bean,并通过自动装配(Auto-wiring)注入依赖关系。
首先,在 XML 配置文件的根元素``中声明了 context 命名空间:
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
这里通过xmlns:context
声明了 context 命名空间
使用组件扫描可以不必在Spring的配置文件中配置各个<bean/>
节点
使用<context:component-scan>
标签来指定需要扫描的基类包:
1 | <context:component-scan base-package="com.stonegeek" /> |
base-package
表示需要扫描的“根包”,当配置后,Spring容器会自动扫描根包下所有类,及各及子包类。
如果只想扫描特定的类而不是基包下的所有类,可以使用resource-pattern
属性:
1 | <context:component-scan base-package="com.baobaotao" resource-pattern="anno/*.class"/> |
这里将基类包设置为com.baobaotao
,并将resource-pattern
属性的值设置为anno/*.class
,表示
Spring
仅会扫描com.baobaotao
包下的anno
子包中的类。默认情况下,resource-pattern
属性的值为**/*.class
,即扫描基类包及其所有子包中的所有类。
以上 xml 配置的目的是:让Spring知道有哪些类,事实上,只是配置组件扫描,Spring并不会创建这些类的对象。如需要Spring创建某些类的对象,还需要为这些类添加注解!
关键注解
@Component
- 作用:标记一个类为 Spring 组件,使其被自动扫描并注册为 Bean。
- 场景:通用的组件标记,适用于任何 Spring 管理的类。
@ComponentScan
作用:指定 Spring 扫描组件的包路径。
位置:通常在配置类上使用。
1
2
3
4
5
public class AppConfig {
// 配置类
}
@Autowired
作用:自动注入依赖,支持构造器、字段、方法注入。
原理:默认按类型(
byType
)匹配,若存在多个候选 Bean,需结合@Qualifier
指定名称。1
2
3
4
5
public class UserController {
private UserService userService; // 字段注入
}
@Repository
- 作用:标记数据访问层(DAO)组件,提供持久化异常转换。
- 场景:通常用于数据库操作类。
@Service
- 作用:标记服务层组件,处理业务逻辑。
- 场景:Service 层类。
@Controller
- 作用:标记 Web 控制器,处理 HTTP 请求。
- 场景:Spring MVC 的控制器类。
@RestController
- 作用:
@Controller
+@ResponseBody
的组合,直接返回 JSON/XML 数据。 - 场景:RESTful API 开发。
- 作用:
@Qualifier
作用:当存在多个同类型的 Bean 时,通过名称指定具体注入的 Bean。
1
2
3
4
5
6
public class OrderService {
// 指定使用名称为paypalPaymentProcessor的Bean
private PaymentProcessor paymentProcessor;
}
@Conditional
作用:根据自定义条件决定是否创建 Bean。
1
2
3
4
5
6
7
8
public class AppConfig {
// 自定义条件
public DataSource productionDataSource() {
// 生产环境数据源
}
}
Bean基于 Java Config 类的配置
除了组件扫描,还可以通过配置类手动定义 Bean:
@Configuration
- 作用:表明该类是一个用于定义 Bean 的配置类。,替代 XML 配置文件。
- 场景:定义 JavaConfig 类。
@Bean
作用:在配置类中定义 Bean,相当于 XML 中的
<bean>
标签。场景:创建第三方库的 Bean 或复杂初始化的 Bean。
1
2
3
4
5
6
7
public class AppConfig {
public DataSource dataSource() {
return new DriverManagerDataSource("jdbc:mysql://localhost:3306/mydb", "user", "pass");
}
}Bean 的类型由方法返回值类型决定,名称默认和方法名相同,也可以通过
name
属性显式指定。例如:1
2
3
4
public UserDao userDao(){
return new UserDao();
}
在普通的POJO类中只要标注@Configuration注解,就可以为spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相当于提供了一个Bean的定义信息。
举例:
1 | package com.example.config; |
1 | package com.example; |
Bean的实例化
首先讲一下什么是 Bean的实例化 什么是 Bean的依赖注入
Bean 的实例化
- 定义:Bean 的实例化是指创建一个 Bean 对象的过程,即将一个类的定义转化为在内存中实际存在的对象。
- 过程:在 Spring 中,Bean 的实例化可以通过多种方式实现,例如使用构造函数、静态工厂方法或实例工厂方法。Spring 容器负责管理 Bean 的生命周期,包括实例化、初始化和销毁。
Bean 的依赖注入 DI
- 定义:依赖注入(Dependency Injection,简称 DI)是一种设计模式,它允许将一个对象的依赖关系(即该对象所依赖的其他对象)通过外部方式(如配置文件或注解)注入到对象中,而不是在对象内部自行创建依赖对象。
- 目的:通过依赖注入,可以实现对象之间的解耦,提高代码的可维护性和可测试性。
- 方式:Spring 支持多种依赖注入方式,主要包括构造函数注入、Setter 方法注入和字段注入。
其中这俩的区别就很明显了:
关注点不同
- 实例化:主要关注如何创建一个对象。
- 依赖注入:关注如何将对象所依赖的其他对象传递给该对象。
作用不同
实例化:是创建对象的基础步骤,为对象的使用做好准备。
依赖注入:实现了对象之间的解耦,使对象的依赖关系更加清晰和灵活。
Bean的实例化之构造方法
Bean的实例化就是Bean是如何创建出来的,Bean本质上就是对象,创建Bean也可以使用构造方法来完成
这个方法是最开始接触Spring时使用的创建对象的方式,只需要在Spring.xml
文件配置
Bean 标签中配置,然后在
test方法中直接通过ApplicationContext
调用getbean()
方法;这是在底层调用了反射技术创建对象;
Spring 默认通过反射调用类的无参构造方法实例化 Bean。若类没有无参构造方法,需显式指定构造参数。
配置方式:在 XML 中使用
<constructor-arg>
标签定义构造参数。
无参构造方法(默认)没有任何变化
1
<bean id="helloWorld" class="cn.qtone.test.HelloWorld" />
等价于 Java 代码
1
HelloWorld helloWorld = new HelloWorld(); // 反射调用无参构造
带参构造方法
假设
HelloWorld
类有以下构造方法:1
2
3
4public HelloWorld(String message, int priority) {
this.message = message;
this.priority = priority;
}1
2
3
4
5
6
7
8<bean id="helloWorld" class="cn.qtone.test.HelloWorld">
<constructor-arg value="Hello Spring!" /> <!-- 按顺序注入字符串 -->
<constructor-arg value="1" /> <!-- 按顺序注入整数 -->
</bean>
<!--或通过索引明确参数位置-->
<constructor-arg index="0" value="Hello Spring!" />
<constructor-arg index="1" value="1" />
Bean的实例化之静态工厂
当 Bean 的创建逻辑复杂(如需要条件判断、缓存等),可将实例化逻辑封装在静态工厂方法中
通过 factory-method
指定静态工厂方法名。
在使用静态工厂实例化Bean时要求开发者在工厂类中创建一个静态方法来创建 Bean 的实例。在配置 Bean 时,class属性指定静态工厂类,同时还需要使用 factory-method 属性指定工厂类中的静态方法
定义静态工厂
1 | public class HelloWorldFactory { |
xml 配置
1 | <bean id="helloWorld" |
获取 Bean
1 | ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); |
Bean 的实例化之实例工厂
实例工厂是指通过一个已存在的实例对象的方法来创建 Bean 实例。
与静态工厂实例方法类似,但是方法是实例方法,在bean的参数额外多了一个
factory-bean
属性标签,用以区分是实例的。
从 spring 容器中获取配置了 factory-method
的 bean
对象时, spring 会自动执行实例工厂的创建对象的方法来返回另一个 bean
对象。
实例工厂方法创建的bean,spring可以管理其生命周期。因为实例工厂bean本身是spring容器管理的bean。
效果:用 getBean 获取配置了 factory-method 的 bean 对象时,返回的是另一个 bean 对象
- 与静态工厂的区别: 静态工厂通过类静态方法创建 Bean,而实例工厂需要先创建工厂类的实例,再通过该实例的普通方法创建目标 Bean。
- 适用场景: 当工厂类本身需要依赖注入或需要 Spring 管理其生命周期时使用。
工厂类定义
1 | public class UserFactory { |
XML 配置
1 | <!-- 1. 先声明工厂类的Bean --> |
id
为userFactory
的 Bean 定义了实例工厂对象。id
为user
的 Bean 通过factory-bean
属性指定了使用userFactory
这个实例工厂,通过factory-method
属性指定了调用createProduct
方法来创建user
对象。
获取 Bean
1 | ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); |
Bean的实例化之FactoryBean
FactoryBean
是一个接口,实现了该接口的类可以作为一个工厂来创建
Bean 实例。用于定制化复杂 Bean 的创建过程。当 Bean
的实例化逻辑非常复杂(如需要多步骤初始化)时,可通过实现
FactoryBean
接口封装逻辑。
Spring 容器在创建使用FactoryBean
的 Bean
时,会调用FactoryBean
的getObject
方法来获取实际的
Bean 实例。
通过 getBean("factoryBeanName")
获取的是
FactoryBean
创建的目标对象,而非
FactoryBean 本身。若需获取 FactoryBean 实例,需在 Bean 名前加
&
(如
getBean("&factoryBeanName")
)。
实现 FactoryBean
接口:重写
getObject()
, getObjectType()
,
isSingleton()
方法。
1 | import org.springframework.beans.factory.FactoryBean; |
XML 配置
1 | <!-- 注册 FactoryBean --> |
获取 Bean
1 | // 获取 FactoryBean 创建的目标对象(User) |
FactoryBean
只需要在配置文件中定义其本身即可,Spring
会自动识别并调用其getObject
方法来创建 Bean。
Bean的依赖注入
依赖注入,英文叫做 Dependency Injection,简称 DI。
DI 和 IoC (《Spring IoC 容器详解》)含义相同,它们是从两个角度描述的同一个概念、做同一件事情。
当某个 Java 实例需要另一个 Java 实例时,使用 Spring 之前都是由调用者创建(使用 new 关键字获得被调用者实例)被调用者的实例,而使用 Spring 框架后,被调用者的实例不再由调用者创建,而是由 Spring IoC 容器创建,这称为控制反转,也即 IoC。
Spring IoC 容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者,这样,调用者通过 Spring IoC 容器获得被调用者实例,这称为依赖注入,也即 DI。
Bean 的依赖注入方式,或叫 Bean 的装配方式,有多种形式,比如接下来要介绍的基于 XML 的依赖注入(有两种实现方式:Setter Injection 属性注入和 Constructor Injection 构造器注入)、基于 Annotation 的依赖注入、基于自动装配、基于静态工厂的方式的依赖注入和基于实例工厂的方式的依赖注入等。
Setter注入(属性注入)
属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。
指 IoC 容器使用 setter 方法注入被依赖的实例。通过调用无参构造器或无参 static 工厂方法实例化 bean 后,调用该 bean 的 setter 方法,即可实现基于 setter 的 DI。
属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。
- 必须提供无参构造器:Spring 通过无参构造器实例化 Bean。
- 必须为属性提供 Setter
方法:格式为
setXxx()
,其中Xxx
是属性名的驼峰写法。
1 | public class UserService { |
xml 配置
1 | <bean id="userDao" class="com.example.dao.UserDaoImpl"/> |
这相当于 Spring 会执行
1 | service.setUserDao(applicationContext.getBean("userDao")); // 后注入 |
注解配置示例
1 |
|
作为 Spring
核心机制的依赖注入,改变了传统的编程习惯,对组件的实例化不再由应用程序完成,转而交由
Spring
容器完成,在需要时注入应用程序中,从而对组件之间依赖关系进行了解耦。这一切都离不开
Spring 配置文件中使用的 <bean>
元素。
Spring 容器可以被看作一个大工厂,而 Spring 容器中的 Bean 就相当于该工厂的产品。如果希望这个大工厂能够生产和管理 Bean,这时则需要告诉容器需要哪些 Bean,以及需要以何种方式将这些 Bean 装配到一起。
Spring 配置文件支持两种不同的格式,分别是 XML 文件格式和 Properties 文件格式。通常情况下,Spring 会以 XML 文件格式作为 Spring 的配置文件,这种配置方式通过 XML 文件注册并管理 Bean 之间的依赖关系。
构造器注入
使用构造函数注入的前提是Bean必须提供带参数的构造函数。例如
- 通过构造器参数注入依赖对象。
- 容器在实例化 Bean 时,直接通过带参构造器完成依赖注入,无需额外调用 Setter 方法。
注意条件
- 必须提供带参构造器:参数类型与依赖对象匹配。
- 依赖对象不可变:构造器注入的依赖通常被声明为
final
。
1 | public class UserService { |
xml 配置
1 | <bean id="userDao" class="com.example.dao.UserDaoImpl"/> |
等价于 Java 代码
1 | new UserService(userDao); // 一步完成实例化和注入 |
注解配置示例
1 |
|
工厂方法注入
工厂方法注入是 Spring 依赖注入的一种方式,通过调用工厂类的方法创建 Bean 实例,分为两种类型:
- 静态工厂方法注入:通过类的静态方法创建 Bean。
- 实例工厂方法注入:通过工厂类的实例方法创建 Bean(需先创建工厂实例)。
静态工厂注入
- 特点:工厂方法为静态方法,无需创建工厂实例。
- 适用场景:工厂类无需维护状态,仅提供创建逻辑。
静态工厂注入就是我们编写一个静态的工厂方法,这个工厂方法会返回一个我们需要的值,然后在配置文件中,我们指定使用这个工厂方法创建bean
。首先我们需要一个静态工厂,如下所示:
1 | public class CarFactory { |
- 静态方法:
createCar
是静态方法,无需创建CarFactory
实例即可调用。- 普通工厂需要先创建工厂实例(如
new CarFactory().createCar()
),而静态工厂直接通过类名调用(如CarFactory.createCar()
),更轻量。
- 普通工厂需要先创建工厂实例(如
- 多态返回:根据传入参数(
electric
或gasoline
)返回不同子类对象。
下面我们需要在xml
中配置car这个bean,并指定它由工厂方法进行创建。配置如下:
通过 <constructor-arg>
向工厂方法传递参数。
1 | <!-- 静态工厂方法配置 --> |
<constructor-arg>
标签:向静态方法传递参数(如"electric"
)。
获取 Bean
1 | ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); |
Spring
容器启动时,会直接调用CarFactory.createCar("electric")
,并将返回的ElectricCar
实例注册为electricCar
Bean。通过Car.class
指定返回类型,确保返回的对象符合预期
非静态工厂注入:
- 特点:需先创建工厂类的实例,再调用实例方法创建 Bean。
- 适用场景:工厂类需要依赖其他 Bean 或维护状态。
有些工厂方法是非静态的,即必须实例化工厂类后才能调用工厂方法。
1 | public class UserFactory { |
工厂类负责创建一个或多个目标类实例,工厂类方法一般以接口或抽象类变量的形式返回目标类实例,工厂类对外屏蔽了目标类的实例化步骤,调用者甚至不用知道具体的目标类是什么。
1 | <!-- 1. 先创建工厂实例 --> |
获取 Bean
1 | ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); |
特性 | 静态工厂方法注入 | 实例工厂方法注入 |
---|---|---|
工厂实例 | 不需要(直接调用静态方法) | 需要(需先创建工厂 Bean) |
配置方式 | class + factory-method |
factory-bean + factory-method |
状态管理 | 无法维护状态(无实例) | 可以维护状态(通过工厂 Bean 属性) |
依赖注入能力 | 无法注入其他 Bean 到工厂类 | 工厂类可以注入其他 Bean 或属性 |
适用场景 | 简单、无状态的创建逻辑 | 复杂、需要依赖或状态管理的创建逻辑 |
使用@Autowired进行自动注入
pring通过@Autowired注解实现Bean的依赖注入,下面是一个例子
1 | package com.baobaotao.anno; |
在①处,我们使用@Service将LogonService标注为一个Bean,在②处,通过@Autowired注入LogDao及UserDao的Bean。@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入到@Autowired标注的变量中。
使用@Autowired的required属性
如果容器中没有一个和标注变量类型匹配的 Bean,Spring 容器启动时将报
NoSuchBeanDefinitionException
的异常。如果希望 Spring
即使找不到匹配的 Bean
完成注入也不用抛出异常,那么可以使用@Autowired(required=false)
进行标注:
1 |
|
默认情况下,@Autowired的required属性的值为true,即要求一定要找到匹配的Bean,否则将报异常。
使用@Qualifier指定注入Bean的名称
如果容器中有一个以上匹配的Bean时,则可以通过@Qualifier注解限定Bean的名称,如下所示:
1 |
|
这里假设容器有两个类型为UserDao的Bean,一个名为userDao,另一个名为otherUserDao,则①处会注入名为userDao的Bean。
对类方法进行标注
@Autowired可以对类成员变量及方法的入参进行标注,下面我们在类的方法上使用@Autowired注解:
1 | package com.baobaotao.anno; |
如果一个方法拥有多个入参,在默认情况下,Spring自动选择匹配入参类型的Bean进行注入。Spring允许对方法入参标注@Qualifier以指定注入Bean的名称,如下所示:
1 |
|
在以上例子中,UserDao的入参注入名为userDao的Bean,而LogDao的入参注入LogDao类型的Bean。
一般情况下,在 Spring 容器中大部分的 Bean
都是单实例的,所以我们一般都无须通过@Repository
、@Service
等注解的value
属性为
Bean 指定名称,也无须使用@Qualifier
按名称进行注入。
集合注入
数组注入
1 | <property name="languages"> |
List 注入
XML 配置
1 | <bean id="collectionBean" class="com.example.CollectionBean"> |
JavaConfig 配置
1 |
|
注解自动装配
1 |
|
Set 注入
XML 配置
1 | <property name="uniqueTags"> |
JavaConfig 配置
1 | bean.setUniqueTags(new LinkedHashSet<>(Arrays.asList("Backend", "Framework"))); |
Map 注入
xml 配置
1 | <property name="configMap"> |
JavaConfig 配置
1 | Map<String, Object> configMap = new HashMap<>(); |
Properties 注入
XML 配置
1 | <property name="dbProperties"> |
JavaConfig 配置
1 | Properties props = new Properties(); |