Spring之IOC(DI)
控制反转 Inversion of Control
依赖注入 Dependency Injection and
下面通过一个例子学习spring的IOC。
一个例子
源代码目录结构如下:
main
service
UserService
dao
UserDao(接口)
UserDaoImpl
model
User
beans.xml
假如我们想实现一个如下功能:调用service层的UserService保存用户数据。在UserService中调用UserDao存入数据库。
在没有spring之前,我们在service层使用dao层功能的时候需要一个实现了UserDao的实例对象,即显式new一个对象。
spring是怎么帮我们做的呢?
如图,我们只需要在配置文件中配置相关信息,spring容器会自动替我们创建对象。
XML配置文件如下:
<bean id="user" class="main.dao.UserDaoImpl">
</bean>
<bean id="userService" class="main.service.UserService">
<property name="userDao" ref="user"></property>
</bean>
test文件
@Test
public void test() {
// 通过指定XML文件得到一个ApplicationContext对象
ApplicationContext context = new ClassPathXmlApplicationContext("main/beans.xml");
// 通过配置文件中的bean得到一个UserService对象
UserService service = (UserService) context.getBean("userService");
service.add();
}
spring是怎么帮我们做的呢?首先解析配置文件,通过反射得到所有的bean对象,调用UserService的setUserDao方法,注入UserDao到userService中。
** 上述例子通过XML配置userService和userDao之间的依赖关系,我们也可通过注解的方式配置两者之间的关系。 **
首先我们需要在配置文件中加入一行配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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:annotation-config/>
<context:annotation-config/>
要记得引入context的约束文件。
接着用注解@Autowired,@Autowired放在如下地方:
- setter
- 构造方法
- 接口
在我们的例子中:
public class UserService {
private UserDao userDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add () {
userDao.save(new User());
}
}
@Autowired 注解默认按类型在bean容器中寻找需要的UserDao,如果UserDao有多个实现怎么办?
这个时候需要另一个注解@Qualifier缩小范围。
它的使用如下:
@Autowired
@Qualifier("main")
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
在XML中配置bean的qualifier属性
<bean id="user" class="main.dao.UserDaoImpl">
<qualifier value="main"></qualifier>
</bean>
其实bean的name是默认的qualifier value,我们也可以用id代替qualifier 元素。
前面的先放一下,来看一段官方文档:
Most examples in this chapter use XML to specify the configuration metadata that produces each BeanDefinition within the Spring container. The previous section demonstrates how to provide a lot of the configuration metadata through source-level annotations. Even in those examples, however, the "base" bean definitions are explicitly defined in the XML file, while the annotations only drive the dependency injection. This section describes an option for implicitly detecting the candidate components by scanning the classpath.Candidate components are classes that match against a filter criteria and have a corresponding bean definition registered with the container. This removes the need to use XML to perform bean registration, instead you can use annotations (for example @Component), AspectJ type expressions, or your own custom filter criteria to select which classes will have bean definitions registered with the container.
在配置文件中加入这句:
<context:component-scan base-package="org.example"/>
一个@Component注解即可让spring自动寻找需要的bean。