Spring 核心技术——IoC 简介

1 IoC 简介

IoC(Inversion Of Control)

即控制反转,也被称为依赖注入。控制反转就是应用本身不负责依赖对象的创建和维护,将对象的创建和维护交给外部容器处理,这样应用的控制权就交给了外部容器,控制权的转移就是控制反转,目的是为了获得更好的维护性以及降低耦合度。

org.springframework.beansorg.springframework.context 包是 IoC 容器的基础,BeanFactoryApplicationContext 接口提供了管理各种对象类型 bean 的功能。

1.1 容器简介

IOC 容器

用来管理应用对象的配置和生命周期,配置每个对象的创建和销毁,也可以配置每个 bean 是否只有一个实例,以及它们是如何相互关联的。

核心配置文件(applicationContext.xml/beans.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 id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

1.1.1 实例化容器

ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

services.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">

    <!-- services -->

    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="itemDao" ref="itemDao"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for services go here -->

</beans>

daos.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 id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for data access objects go here -->

</beans>

对于大型项目,通常可以分模块定义 bean,然后再整合到一个统一的配置文件中,方便管理。

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

1.1.2 使用容器

// create and configure beans
ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();

1.2 Bean 简介

Spring IoC 容器管理一个或多个 bean。这些 bean 都是 Spring 根据配置文件创建的。

bean 主要有如下定义:

  • class: bean 对应的类的全限定名
  • id/name: bean 对应的配置文件中的唯一标识
  • scope: bean 的作用域
  • constructor arguments: bean 的构造参数
  • properties: bean 的注入类型
  • autowiring mode: bean 自动注入
  • lazy-initialization mode: bean 懒加载
  • initialization method: bean 的初始化
  • destrcution method: bean 的销毁

具体会在之后做相关说明。

1.2.1 bean 命名

在配置文件中,可以使用 id 或者 name 属性指定 bean 的唯一标识。

在 3.1 的版本前,id 属性的值必须遵循 xml 中 id 属性的规范,对于一些特殊字符,xml 是无法解析,此时就可以使用 name 来指定;从 3.1 版本开始,id 属性值只要遵循 xml 中 string 的规范就行,即使是特殊字符,xml 也可以解析,但 id 的唯一性仍需要保证。因为 3.1 版本放宽了 id 属性的规范,此时,id 和 name 的区别已不大,但 name 属性还可以为一个 bean 指定多个名字(多个名字之间用 ,; 或空格隔开),这个是 id 所不具备的。

另外,bean 的命名不是必须提供的,如果省略,Spring 会自动生成一个唯一的名字,只是这样我们就无法通过 id/name 来实例化 bean,不过,它仍然有它的用途(如:内部 bean,自动注入等),具体会在之后的文章中说明。

除了直接通过 id/name 属性指定 bean 的名字,还可以通过 alias 来为 bean 再指定别名,不过,此时通过别名和原 bean 名实例化的 bean 对象是同一个,即只会实例化一次。

<alias name="fromName" alias="toName"/>

1.2.2 实例化 bean

在配置文件中定义的 bean,默认情况下,会在 IoC 容器实例化的时候全部实例化,通过各自的默认无参构造方法

1.2.2.1 通过默认的构造方法

只要做如下配置,在 IoC 容器实例化时,对应的 bean 就会自动调用默认的无参构造器初始化。

<bean id="exampleBean" class="examples.ExampleBean"/>

<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
1.2.2.2 通过工厂方法
  • 静态工厂

此处定义的 bean 为目标 bean。由于目标 bean 是通过工厂的静态方法生成的,所以无需实例化工厂 bean。目标 bean 的定义中,class 对应静态工厂的类名,factory-method 指定的是生成目标 bean 的静态工厂方法。

<bean id="clientService"
    class="examples.ClientService"
    factory-method="createInstance"/>
public class ClientService {
    private static ClientService clientService = new ClientService();
    private ClientService() {}

    public static ClientService createInstance() {
        return clientService;
    }
}
  • 实例工厂

区别于静态工厂,此处需要先实例化工厂 bean,再通过工厂 bean 的方法实例化目标 bean。此时,目标 bean 的定义中,bean-factory 为工厂 bean 的 id,factory-method 为工厂 bean 中生成目标 bean 的工厂方法。

<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<!-- the bean to be created via the factory bean -->
<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>
public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();
    private DefaultServiceLocator() {}

    public ClientService createClientServiceInstance() {
        return clientService;
    }
}
  • 一个工厂类也可以实现多个工厂方法,生成多个 bean。
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>

<bean id="accountService"
    factory-bean="serviceLocator"
    factory-method="createAccountServiceInstance"/>
public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();
    private static AccountService accountService = new AccountServiceImpl();

    private DefaultServiceLocator() {}

    public ClientService createClientServiceInstance() {
        return clientService;
    }

    public AccountService createAccountServiceInstance() {
        return accountService;
    }
}
  • 带参数的工厂

如果工厂方法有参数,必须通过 <constructor-arg> 标签来配置,而不是 <property>

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    private ExampleBean(...) {
        ...
    }

    public static ExampleBean createInstance (
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

        ExampleBean eb = new ExampleBean (...);
        // some other operations...
        return eb;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值