Spring Bean 配置详解
一、Bean的基本概念
在Spring框架中,Bean是指由Spring IoC容器管理的对象。Spring IoC容器负责创建Bean实例、管理Bean的生命周期、以及维护Bean之间的依赖关系。
二、Bean配置的主要方式
Spring提供了多种配置Bean的方式,包括XML配置、注解配置和Java配置。
1. XML配置方式
XML配置是Spring早期最常用的配置方式,通过XML文件定义Bean的信息。
基本配置
xml
<?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配置 -->
<bean id="userService" class="com.example.UserService">
<!-- 属性注入 -->
<property name="userRepository" ref="userRepository"/>
</bean>
<bean id="userRepository" class="com.example.UserRepository"/>
</beans>
构造器注入
xml
<bean id="userService" class="com.example.UserService">
<!-- 构造器注入 -->
<constructor-arg ref="userRepository"/>
</bean>
集合类型属性配置
xml
<bean id="userService" class="com.example.UserService">
<property name="stringList">
<list>
<value>value1</value>
<value>value2</value>
</list>
</property>
<property name="stringMap">
<map>
<entry key="key1" value="value1"/>
<entry key="key2" value="value2"/>
</map>
</property>
</bean>
2. 注解配置方式
随着Spring的发展,注解配置逐渐成为主流,它简化了配置代码,提高了开发效率。
常用的Bean注解
@Component
:通用的组件注解,可用于任何Bean@Repository
:用于数据访问层(DAO层)的Bean@Service
:用于业务层(Service层)的Bean@Controller
:用于控制层(MVC中的Controller)的Bean@Configuration
:用于配置类的Bean
示例代码
java
// 在类上添加注解,将其声明为Spring Bean
@Service
public class UserService {
// 使用@Autowired注解进行依赖注入
@Autowired
private UserRepository userRepository;
// 业务方法
public User getUserById(Long id) {
return userRepository.findById(id);
}
}
@Repository
public class UserRepository {
public User findById(Long id) {
// 模拟数据库查询
return new User(id, "张三");
}
}
组件扫描配置
要使注解配置生效,需要在配置文件中开启组件扫描:
XML配置方式:
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启组件扫描 -->
<context:component-scan base-package="com.example"/>
</beans>
Java配置方式:
java
@Configuration
@ComponentScan("com.example") // 指定要扫描的包
public class AppConfig {
// 配置类
}
3. Java配置方式
Java配置是Spring 3.0引入的新特性,通过Java类和注解来配置Bean,完全替代XML配置。
基本配置
java
@Configuration // 标记为配置类
public class AppConfig {
// 使用@Bean注解定义Bean
@Bean
public UserRepository userRepository() {
return new UserRepository();
}
@Bean
public UserService userService() {
UserService userService = new UserService();
// 手动注入依赖
userService.setUserRepository(userRepository());
return userService;
}
// 或者通过构造器注入
@Bean
public UserService userService(UserRepository userRepository) {
return new UserService(userRepository);
}
}
三、Bean的作用域配置
Spring提供了多种Bean的作用域,用于控制Bean的生命周期和创建方式:
1. 常用作用域
- singleton:单例模式,Spring IoC容器中只会存在一个Bean实例(默认作用域)
- prototype:原型模式,每次请求都会创建一个新的Bean实例
- request:在Web应用中,每个HTTP请求都会创建一个新的Bean实例
- session:在Web应用中,每个HTTP会话会创建一个新的Bean实例
- application:在Web应用中,每个ServletContext会创建一个新的Bean实例
2. 作用域配置方式
XML配置方式:
xml
<bean id="userService" class="com.example.UserService" scope="prototype"/>
注解配置方式:
java
@Service
@Scope("prototype")
public class UserService {
// 类内容
}
Java配置方式:
java
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public UserService userService() {
return new UserService();
}
}
四、Bean的生命周期配置
Spring允许在Bean的生命周期的特定点执行自定义逻辑。
1. 初始化和销毁方法
XML配置方式:
xml
<bean id="userService" class="com.example.UserService"
init-method="init" destroy-method="destroy"/>
注解配置方式:
java
@Service
public class UserService {
// 初始化方法
@PostConstruct
public void init() {
// 初始化逻辑
}
// 销毁方法
@PreDestroy
public void destroy() {
// 销毁逻辑
}
}
Java配置方式:
java
@Configuration
public class AppConfig {
@Bean(initMethod = "init", destroyMethod = "destroy")
public UserService userService() {
return new UserService();
}
}
2. BeanPostProcessor接口
通过实现BeanPostProcessor接口,可以在Bean的初始化前后执行自定义逻辑:
java
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// 在Bean初始化之前执行
if (bean instanceof UserService) {
System.out.println("UserService初始化前处理");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 在Bean初始化之后执行
if (bean instanceof UserService) {
System.out.println("UserService初始化后处理");
}
return bean;
}
}
五、Bean的自动装配
自动装配(Autowiring)是Spring的一个重要特性,它可以自动注入Bean的依赖关系。
1. XML配置的自动装配
xml
<!-- byName:根据属性名自动装配,查找与属性名同名的Bean -->
<bean id="userService" class="com.example.UserService" autowire="byName"/>
<!-- byType:根据属性类型自动装配,查找与属性类型匹配的Bean -->
<bean id="userService" class="com.example.UserService" autowire="byType"/>
<!-- constructor:通过构造器自动装配,查找与构造器参数类型匹配的Bean -->
<bean id="userService" class="com.example.UserService" autowire="constructor"/>
<!-- autodetect:自动检测使用byType还是constructor -->
<bean id="userService" class="com.example.UserService" autowire="autodetect"/>
2. 注解的自动装配
java
@Service
public class UserService {
// byType自动装配
@Autowired
private UserRepository userRepository;
// 可以指定required=false,表示依赖不是必须的
@Autowired(required = false)
private LogService logService;
// 也可以使用@Qualifier指定要注入的Bean的名称
@Autowired
@Qualifier("specialUserRepository")
private UserRepository specialUserRepository;
// JDK标准注解@Resource,默认byName自动装配
@Resource(name = "userRepository")
private UserRepository userRepository2;
}
六、基于Java的条件化Bean配置
Spring 4.0引入了条件化配置,可以根据特定条件决定是否创建Bean。
java
@Configuration
public class AppConfig {
// 只有当DataSource类在类路径上时,才会创建dataSource Bean
@Bean
@Conditional(DataSourceCondition.class)
public DataSource dataSource() {
// 创建并配置DataSource
return new HikariDataSource(config);
}
}
// 自定义条件类
public class DataSourceCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
try {
// 检查DataSource类是否存在
Class.forName("javax.sql.DataSource");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
七、Bean配置的继承
Spring允许Bean配置继承,减少重复配置。
xml
<!-- 父Bean定义 -->
<bean id="abstractService" abstract="true">
<property name="dao" ref="dao"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<!-- 子Bean继承父Bean的配置 -->
<bean id="userService" class="com.example.UserService" parent="abstractService">
<!-- 可以覆盖父Bean的配置 -->
<property name="specialProperty" value="specialValue"/>
</bean>
总结
Spring提供了灵活多样的Bean配置方式,包括XML配置、注解配置和Java配置,开发者可以根据项目需求选择合适的配置方式。Bean配置的主要内容包括Bean的定义、作用域、生命周期、自动装配等方面。随着Spring的发展,注解配置和Java配置越来越受到青睐,它们简化了配置代码,提高了开发效率。在实际项目中,通常会结合使用多种配置方式,充分利用Spring框架的强大功能。