Spring依赖注入详解:从入门到实战
Spring依赖注入详解:从入门到实战
Spring框架的核心特性之一就是依赖注入(Dependency Injection,简称DI),它使得组件之间的依赖关系可以由容器来管理,而不是在代码中硬编码。本文将从入门到深入,详细讲解Spring中的依赖注入机制,包括依赖注入的基本概念、实现方式以及数据类型注入等内容。
1. Bean的依赖注入入门
1.1 基本概念
在Spring框架中,依赖注入是通过控制反转(Inversion of Control,简称IoC)容器来实现的。IoC容器负责管理应用程序中的对象(即Bean),并处理它们之间的依赖关系。
1.2 创建UserService
假设我们有一个UserService
接口,它需要调用UserDao
的save()
方法。在没有使用Spring的情况下,我们通常会在UserService
的实现类中直接创建UserDao
的实例:
public class UserServiceImpl implements UserService {
@Override
public void save() {
UserDao userDao = new UserDaoImpl();
userDao.save();
}
}
但是,使用Spring后,我们可以将UserDao
的创建权交给Spring容器:
<bean id="userDao" class="com.xdr630.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.xdr630.service.Impl.UserServiceImpl"></bean>
然后在测试类中从Spring容器中获取UserService
实例:
public class UserController {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
}
2. Bean的依赖注入分析
在上述例子中,UserService
和UserDao
都存在于Spring容器中。为了更好地解耦,我们希望在Spring容器内部完成它们之间的依赖关系。具体来说,就是将UserDao
注入到UserService
中。
3. Bean的依赖注入概念
依赖注入(Dependency Injection)是Spring框架核心IoC的具体实现。在使用Spring之前,组件之间的依赖关系通常需要在代码中硬编码。而使用Spring后,这些依赖关系可以由Spring容器来管理,从而实现真正的解耦。
4. Bean的依赖注入方式
4.1 构造方法注入
构造方法注入是最直接的方式。我们可以在UserServiceImpl
中添加一个有参构造方法:
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
}
然后在配置文件中使用<constructor-arg>
标签进行注入:
<bean id="userDao" class="com.xdr630.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.xdr630.service.Impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
4.2 Setter方法注入
Setter方法注入是另一种常见的注入方式。我们可以在UserServiceImpl
中添加一个setUserDao
方法:
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
}
}
然后在配置文件中使用<property>
标签进行注入:
<bean id="userDao" class="com.xdr630.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.xdr630.service.Impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
4.3 P命名空间注入
P命名空间注入本质上也是Setter方法注入,但配置起来更加方便。首先需要在配置文件中引入P命名空间:
xmlns:p="http://www.springframework.org/schema/p"
然后可以直接在<bean>
标签中使用p:
前缀进行注入:
<bean id="userService" class="com.xdr630.service.Impl.UserServiceImpl" p:userDao-ref="userDao"/>
5. Bean的依赖注入的数据类型
除了对象引用,Spring还支持普通数据类型、集合数据类型等的注入。
5.1 普通数据类型的注入
假设UserDao
需要一些基本属性,如用户名和年龄:
public class UserDaoImpl implements UserDao {
private String username;
private int age;
public void setUsername(String username) {
this.username = username;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void save() {
System.out.println("username=" + username + "\n" + "age=" + age);
System.out.println("save running......");
}
}
可以在配置文件中使用<property>
标签进行注入:
<bean id="userDao" class="com.xdr630.dao.impl.UserDaoImpl">
<property name="username" value="xdr"/>
<property name="age" value="22"/>
</bean>
5.2 集合数据类型的注入
5.2.1 List类型的注入
假设UserDao
需要一个List<String>
类型的属性:
public class UserDaoImpl implements UserDao {
private List<String> strList;
public void setStrList(List<String> strList) {
this.strList = strList;
}
public void save() {
System.out.println(strList);
System.out.println("save running......");
}
}
可以在配置文件中使用<list>
标签进行注入:
<bean id="userDao" class="com.xdr630.dao.impl.UserDaoImpl">
<property name="strList">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
</bean>
5.2.2 Map类型的注入
假设UserDao
需要一个Map<String, User>
类型的属性:
public class UserDaoImpl implements UserDao {
private Map<String, User> userMap;
public void setUserMap(Map<String, User> userMap) {
this.userMap = userMap;
}
public void save() {
System.out.println(userMap);
System.out.println("save running......");
}
}
可以在配置文件中使用<map>
标签进行注入:
<bean id="userDao" class="com.xdr630.dao.impl.UserDaoImpl">
<property name="userMap">
<map>
<entry key="u1" value-ref="user1"></entry>
<entry key="u2" value-ref="user2"></entry>
</map>
</property>
</bean>
<bean id="user1" class="com.xdr630.domain.User">
<property name="name" value="tom"/>
<property name="addr" value="beijing"/>
</bean>
<bean id="user2" class="com.xdr630.domain.User">
<property name="name" value="jerry"/>
<property name="addr" value="shanghai"/>
</bean>
5.2.3 Properties类型的注入
假设UserDao
需要一个Properties
类型的属性:
public class UserDaoImpl implements UserDao {
private Properties properties;
public void setProperties(Properties properties) {
this.properties = properties;
}
public void save() {
System.out.println(properties);
System.out.println("save running......");
}
}
可以在配置文件中使用<props>
标签进行注入:
<bean id="userDao" class="com.xdr630.dao.impl.UserDaoImpl">
<property name="properties">
<props>
<prop key="p1">ppp1</prop>
<prop key="p2">ppp2</prop>
<prop key="p3">ppp3</prop>
</props>
</property>
</bean>
6. 引入其他配置文件(分模块开发)
在实际开发中,Spring的配置内容可能非常庞大,因此可以将配置拆分成多个配置文件。例如:
<import resource="applicationContext-xxx.xml"/>
这样,只需要加载主配置文件,其他配置文件就会被自动加载。
7. Spring的重点配置
在Spring配置文件中,<bean>
标签是最核心的配置元素,它包含了以下重要属性:
id
:Bean的唯一标识class
:Bean的全限定名scope
:Bean的作用范围,常用的是Singleton(默认)和prototype
<property>
标签用于属性注入,可以注入普通属性值或对象引用值。<constructor-arg>
标签用于构造方法注入。<import>
标签用于导入其他配置文件。
通过本文的讲解,相信读者已经对Spring框架中的依赖注入有了全面的了解。掌握这些知识,将有助于开发出更加灵活、可维护的Java应用程序。