Spring中Ioc的两种方式

140 阅读3分钟

文章目录


1. 概述

控制反转(Inversion of Control,Ioc)是指将创建对象的权利交给框架,它是框架的重要特征,并非面向对象编程的专用术语。它主要包含依赖注入(Dependency Injection)和依赖查找(Dependency Lookup)。
在这里插入图片描述
其中依赖注入是被动的接收其依赖的其它组件被Ioc容器注入;而依赖查找是主动的去某个服务注册地查找其依赖的那些服务。它们之间的关系如下所示:
在这里插入图片描述


2. Ioc依赖注入

Ioc的依赖注入可以分为两个流程:

  • 收集和注册
  • 分析和组装

2.1 收集和注册

在这个阶段中,Spring可以通过XML配置文件或是注解代码的方式来定义一些Bean,然后通过手动组装或者让Ioc容器基于某些机制自动扫描的方式,将定义好的Bean收集到Ioc容器中。

例如,通过XML文件的形式配置<bean></bean>标签来手动的收集并注册Bean:

<?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="accountService" class="dyliang.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <bean id="accountDao" class="dyliang.dao.impl.IAccountDaoImpl">
        <property name="runner" ref="runner"></property>
    </bean>
</beans>

​ 通过@Component@Repository@Service@Controller注解来让Spring帮程序收集并注册定义的Bean

@Service("accountService")
public class AccountServiceImpl implements IAccountService {}
@Repository("accountDao1")
public class AccountDaoImpl implements IAccountDao {}

如果嫌逐个收集 bean 定义麻烦,想批量地收集并注册到 IoC 容器中,我们也可以通过 XML Schema 形式的配置进行批量扫描并采集和注册:

<context:component-scan base-package="xxxx">

2.2 分析和组装

经过收集和注册阶段得到的Ioc容器中的Bean,它们之间此时并没有任何关系,但实际中不同Bean之间会存在某些依赖,这就需要分析和组装阶段来完成。

如果 IoC 容器发现某个 bean 依赖另一个 bean,它就会将这另一个 bean 注入给依赖它的那个 bean,直到所有 bean 的依赖都注入完成。当所有的bean都组装结束,整个 IoC 容器的工作即算完成。

例如,XML文件中通过<bean>标签内部的<property>标签的ref属性来指向另一个Bean,表示两者之间的依赖关系。或者使用@Autowired@Inject等注解在Bean对应的类内部定义依赖类的对象,让Spring帮我们自动注入,完成依赖关系的绑定。

<bean id="accountService" class="dyliang.service.impl.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"></property>
</bean>

<bean id="accountDao" class="dyliang.dao.impl.IAccountDaoImpl">
    <property name="runner" ref="runner"></property>
</bean>
@Service("accountService")
public class AccountServiceImpl implements IAccountService {

    @Autowired
    @Qualifier("accountDao")
    private IAccountDao accountDao;
}

3. Ioc依赖查找

在Spring项目的测试类中,可以通过如下代码获取XML配置文件形式对应的Ioc容器:

ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

得到Ioc容器后通过getBean()方法来获取对应的Bean的过程就是依赖查找,其中Bean()可以接受三种类型的参数

  • Bean_ID.class

    AccountService service = ac.getBean(AccountService.class);
    
  • Bean name

    AccountService service = ac.getBean("accountService");
    
  • Bean_ID.class, Bean name

    AccountService service = ac.getBean(AccountService.class, "accountService");
    

或者通过@ContextConfiguration注解来通过Spring自动获取容器,然后在类中定义要使用的Bean对象,并通过@Autowired自动注入来获取Bean,最后只需要使用Bean中相应的方法即可。

@ContextConfiguration(locations = "classpath:bean.xml")
public class AccountTest {
    
    @Autowired
    private IAccountService as;

    @Test
    public void testFindAll(){
        List<Account> all = as.findAll();
        for (Account account : all) {
            System.out.println(account);
        }
    }
}