对 Spring IOC 机制及其配置方式的的总结

本文详细介绍了Spring Ioc容器的基本原理,包括BeanFactory和ApplicationContext的使用。重点阐述了Spring的配置方式,如XML配置的结构、自动装配、基于Java的配置以及如何混合使用多种配置方式。通过解析XML配置的beans、import、alias和bean标签,以及Java配置和注解的使用,帮助读者理解Spring Ioc的配置技巧。
摘要由CSDN通过智能技术生成

1、Spring Ioc 的基本原理:BeanFactory

Spring Ioc 容器的代表就是 BeanFactory 接口,它其中定义了一些获取 Bean 的方法 getBean()ApplicationContext 接口扩展了 BeanFactory,还提供了与 Spring AOP 集成、国际化处理、事件传播及提供不同层次的 context 实现。我们可以从 BeanFactory 和 ApplicationContext 任选一个来使用,但是 BeanFactory 过于低级,所以 ApplicationContext 用得更加广泛。

ApplicationContext 有多个具体的实现,以供我们从不同类型的配置文件中获取 Bean 实例。以下是比较常用的一些:

  1. AnnotationConfigApplicationContext:从一个或多个基于 Java 的配置类中加载应用上下文
  2. AnnotationConfigWebContextLoader:从一个或多个基于 Java 配置类中加载 Web 应用上下文
  3. ClassPathXmlApplicationContext:从类路径下面一个或多个配置文件中加载上下文
  4. FileSystemXmlApplicationContext:从文件系统中的一个或多个配置文件中加载上下文
  5. 其他……

以 AnnotationConfigApplicationContext 为例,其继承关系如下:

AnnotationConfigApplicationContext 继承关系

当获取到了 ApplicationContext 之后,我们就可以使用它来获取 Bean 实例。ApplicationContext 从 BeanFactory 继承了一系列方法用来获取 Bean 实例:

    Object getBean(String var1) throws BeansException;
    <T> T getBean(Class<T> var1) throws BeansException;
    <T> Map<String, T> getBeansOfType(Class<T> var1) throws BeansException;

这里我们给的是三种基本的方法,它们还有一些多态的方法。与其区别仅在于,增加了一些可选的参数。

以 AnnotationConfigApplicationContext 的使用为例。我们只需要使用注解指定一个配置类,并通过注解指定扫描的包的地址,然后系统会自动对包进行扫描,装载 Bean 并进行管理,

    @Configurable
    @ComponentScan(value = "me.shouheng.spring.componentscan")
    public class ComponentScanConfiguration {
    }

然后,我们就可以获取 AnnotationConfigApplicationContext 实例,并从中来获取系统管理的 Bean 了,

    public static void main(String...args) {
        // 指定 Spring 容器的配置类为 ComponentScanConfiguration
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ComponentScanConfiguration.class);
        // 通过 Bean 类的 Class 类型获取 Bean 实例
        FirstBean firstBean = context.getBean(FirstBean.class);
        firstBean.say();
    }

当然,自定了扫描的包之后,我们还需要通过注解来指定哪些类是我们的 Bean 实例,以及它们在 Spring 容器中的表现,比如单例还是每次实例化一个实例等等,稍后我们会对其进行总结。

除了使用 Java 类和注解,我们还可以在 XML 中配置 Spring 容器。在早期的 Spring 版本中,这是比较常用的一种配置方式。它的实现方式也很简单,即使用 ClassPathXmlApplicationContext 类,通过构造方法指定 XML 配置文件的路径,拿到了 ClassPathXmlApplicationContext 实例之后,用它的方法获取 Bean 即可,

    public static void main(String...args) {
        // 系统会到 resources 目录下面的 componentscan 目录下面的 ComponentScan.xml 文件中寻找 Bean 实例
        ApplicationContext context = new ClassPathXmlApplicationContext("componentscan/ComponentScan.xml");
        // 通过 Bean 类的 Class 类型获取 Bean 实例
        FirstBean firstBean = context.getBean(FirstBean.class);
        firstBean.say();
    }

上面是 Spring 的容器作用的基本原理,即指定了扫描的路径之后,Spring 容器会对路径自动扫描,装载 Bean,然后自动对其进行管理。显然,相对于我们显式地进行管理,它使用起来更加方便。不过,上面是它作用的基本原理。Spring 容器理解起来并不难,只是它的各种配置方式比较灵活,需要整理下才能更好的掌握。下面我们对 Spring 的常用的配置方式进行总结。

2、Spring Ioc 的配置

如上所述,早期的 Spring 通过 XML 配置的方式比较多,后来则提出了通过注解和 Java 类来进行配置的方式。下面我们来对两种配置方式进行梳理。

2.1 Xml 配置的结构

当我们使用 XML 来配置 Bean 的时候,其基本的格式如下(这里我们省略了命名空间的声明):

    <beans xmlns=...>
        <import resource="../hello/HelloWorld.xml"/>
        <bean id="universal" class="me.shouheng.spring.universal.UniversalBean"/>
        <alias name="universal" alias="my_universal"/>
    </beans>

在 XML 中主要下面几种类型标签供我们使用:

  1. import:用于导入其他的 XML 配置文件,这样就可以让我们对配置文件进行功能分类;
  2. bean:用来声明 Bean;
  3. alias:用来为一个 Bean 起一个别名;
  4. beans:beans 根标签中还可以加入 beans 子标签;
  5. description:文件描述

注:可以在 IDEA 中通过点击标签或者标签的属性进入到 spring-beans.xml 中查看各个标签的定义和解释。

2.1.1 beans 标签

beans 标签中有几个属性需要注意下,

属性取值范围说明
profile字符串可类型用来快速切换 beans 环境,比如生成环境和开发测试环境等
default-lazy-init取值范围为 defaul, true 和 false同 bean 标签的 lazy-init 属性含义相同,即延迟初始化,表示只有在用到的时候才会被初始化,默认为 default,即继承外部 beans 的属性,否则为 false
default-autowire取值范围为 defaul, no, byName, byType 和 constructor同 bean 标签的 autowire 属性含义相同,即表示自动注入的方式。默认值为 default,即继承外部 beans 的属性,否则使用 no.
default-autowire-candidates字符串类型同 bean 标签的 autowire-candidate 属性,通过名称样式匹配注入的对象,比如 “Service", "data” 等。
default-init-method字符串类型同 bean 标签的 init-method 属性,接收字符串类型。可以写入 Bean 的方法名称,当该 beans 标签中的任何 bean 被创建的时候,都会调用该方法。
default-destroy-method字符串类型同 bean 标签的 destroy-method 属性,接收字符串类型。可以指定 Bean 的方法名称,当该 beans 标签中的任何 bean 被销毁的时候,都会调用该方法。

特别说明:

1. profile 属性的特别说明

profile 属性用来快速切换 beans 环境,比如生成环境和开发测试环境等。使用方式是在 XML 配置文件中的末尾处通过如下方式添加如下代码:

    <beans profile="dev">
        <context:component-scan base-package="me.shouheng.spring.componentscan"/>
    </beans>
    <beans profile="dev2">
        <context:component-scan base-package="me.shouheng.spring.componentscan2"/>
    </beans>

激活配置的方式有以下几种:

  1. 在 web.xml 中通过 context-param 指定,注意这里定义的是 default 值,在非生产环境,可以用系统变量 spring.profiles.active 进行覆盖:
<context-param>
    <param-name>spring.profiles.default</param-name>
    <param-value>production</param-value>
</context-param>
  1. 启动 main 方法的时候在 Run Configuration 中通过修改虚拟机参数 VM Options 进行修改。比如 -Dspring.profiles.active="dev2"

  2. 单元测试的时候通过注解 @ActiveProfiles("dev2") 来指定。

2.1.2 import 标签

import 标签可以指定多种数据源的配置文件,常用的如下,包括 class 路径、resource 目录下的 xml 中,文件系统和网络:

    <beans xmlns=...>
        <import resource="classpath:"/>
        <import resource="classpath*:"/>
        <import resource="DiConfig.xml"/>
        <import resource="file:"/>
        <import resource="http:"/>
    </beans>

这里 classpathclasspath* 的区别是:classpath 只会到你的 class 路径中查找找文件;而 classpath* 不仅包含 class 路径,还要到 jar 文件中(class 路径)进行查找。可以在 classpath 路径上使用通配符 * 进行模糊查找,比如 classpath:applicationContext-*.xml

2.1.3 alias 标签

用来为 bean 指定别名,接收两个参数,一个是 name,即 bean 原来的名称;一个是 alisa,即 bean 的新的别名。

    <bean id="hello" class="me.shouheng.spring.hello.beanimp.HelloApiImpl"/>
    <alias name="hello" alias="h"/>
2.1.4 bean 标签

bean 标签用来指定我们的 bean 实例的构造方式,用来为 bean 的属性赋值等等。它的属性和子元素比较多,可以通过 spring-bases.xml 中的 beansAttributes 和 beanElements 两个分组来查看。

1. bean 标签的属性

属性名称类型和取值范围说明
id字符串类型bean 的唯一的 id,同一 beans 标签中同一 id 不可以被多次使用
name字符串类型用来指定 bean 的名称,多个 name 之间使用 ,, ; 或者 分割
class字符串类型用来指定 bean 的类型,除非该 bean 只作为其他 bean 的父 bean 使用
parent字符串类型用来指定父 bean 的 name
scope字符串类型,取值 request, session, prototypesingleton用来表示 bean 以何种方式创建,以及生命周期。
abstract布尔类型默认 false,用来指定该 bean 是否作为其他的 bean 的父 bean 使用。如果使 true,那么这种 bean 不会被初始化。
lazy-init取值范围为 defaul, true 和 false延迟初始化,表示只有在用到的时候才会被初始化,默认为 default,即继承外部 beans 的属性,否则为 false。
autowire取值范围为 defaul, no, byName, byType 和 constructor表示自动注入的方式,默认值为 default,即继承外部 beans 的属性,否则使用 no.
depends-on字符串类型对两个 Bean,A 和 B,若在 A 的配置中设置它的 depends-on 属性为 B,那么 A 会在 B 初始化完成之后再被创建,而 B 要等到 A 销毁了之后才能被销毁
autowire-candidate
primary布尔类型
init-method字符串类型可以写入 Bean 的方法名称,当该 beans 标签中的任何 bean 被创建的时候,都会调用该方法。
destroy-method字符串类型可以指定 Bean 的方法名称,当该 beans 标签中的任何 bean 被销毁的时候,都会调用该方法。
factory-method字符串类型与 factory-bean 属性配合使用。系统创建 Bean 的时候,使用 factory-bean 指定的工厂 Bean 和 factory-method 指定工厂方法创建该 Bean 实例
factory-bean字符串类型见 factory-method 属性

2. Bean 标签属性的特别说明

  1. scope 属性的四个取值的说明

    1. singleton 表示单例作用域,每个容器中只会存在一个实例,而且其完整生命周期完全由 Spring 容器管理。默认就是单例的。如果 Bean 是延迟初始化的,那么该 Bean 会在首次使用的时候创建并放在单例缓存池中。
    2. prototype 表示原型,每次向容器请求获取 Bean 都返回一个全新的 Bean,即每次都创建的全新 Bean。
    3. request 表示每个请求需要容器创建一个全新 Bean。比如提交表单的数据必须是对每次请求新建一个 Bean 来保持这些表单数据,请求结束释放这些数据。
    4. session 作用域表示每个会话需要容器创建一个全新 Bean。比如对于每个用户一般会有一个会话,该用户的用户信息需要存储到会话中,此时可以将该 Bean 配置为 web 作用域。
  2. 延迟初始化 lazy-init

    1. 延迟初始化适用于可能需要加载很大资源,而且很可能在整个应用程序生命周期中很可能使用不到的 Bean。
    2. <beans> 标签中通过制定 default-lazy-init="true" 可以将内部全部 bean 延迟初始化。
  3. init-method和destroy-method:在 Bean 标签中通过这 init-method 和 destroy-method 分别指定初始化时和销毁时调用的方法。

    1. init-method:指定初始化方法,在构造器注入和 setter 注入完毕后执行;
    2. destroy-method:指定销毁方法,只有 singleton 作用域能销毁,prototype 作用域的一定不能,其他作用域不一定能;
    3. 可以使用 @PostConstruct@PreDestroy 注解标记指定的方法来实现生命周期回调,要使用这种方式还要在 XML 中加入 <context:annnotation-config> 标签,或者使用 <context:component-scan/>
    4. 实现生命周期的第三种选择是实现 InitializingBeanDisposableBean 接口。
  4. 自动装配属性 autowire:自动装配就是指由 Spring 来自动地注入依赖对象,无需人工参与。Spring 支持 nobyNamebyTypeconstructordefault 5 种自动装配,默认是 no 指不支持自动装配。byName 表示按照名称装配,byType 表示按照类型自动装配,constructor 也是按照类型来装配的,只是用于构造器注入方式。我们来总结一下自动装配相关的内容:

    1. 不是所有类型都能自动装配,Object、基本数据类型等无法自动装配;
    2. 数组、集合、字典类型的根据类型自动装配和普通类型的自动装配是有区别的,它们需要根据泛型信息注入;
    3. 自动装配的缺点就是没有了配置,在查找注入错误时非常麻烦,还有比如基本类型没法完成自动装配,所以可能经常发生一些莫名其妙的错误;
    4. 自动装配注入和配置注入同时存在时,配置注入的数据会覆盖自动装配注入的数据;
    5. 自动装配要求被装配的 Bean 中的对象实例有 Setter 方法。
    6. 下面是自动装配的一个示例:

我们定义如下的 FirstBean,它其中有一个 SecondBean 类型的实例字段,并且有一个 Setter 方法:

public class FirstBean {
    
    private SecondBean secondBean;
    
    public void setSecondBean(SecondBean secondBean) {
        this.secondBean = secondBean;
    }
}

那么,我们按照如下的方式进行自动装配:

    <bean name="firstBean" class="me.shouheng.spring.autowire.FirstBean" autowire="byName"/>
    <bean name="secondBean" class="me.shouheng.spring.autowire.SecondBean" />

3. bean 标签的子元素

这里的标签主要有:metaconstructor-argqualifierlookup-methodreplaced-method

  • meta 标签:用来给 Bean 添加一个任意的 Metadata 信息,以键值对的形式;

  • constructor-arg 标签:用来通过构造函数注入属性值,以创建 Bean 实例。它可以包含的属性包括

    • index 属性:字符串类型,用来指定当前参数在构造函数的参数列表中的位置,以放在当构造函数参数列表中存在两个相同类型参数的情形
    • type 属性:字符串类型,用来指定当前构造函数的参数的类型。
    • name 属性:字符串类型,用来指定当前构造函数的参数的名称。
    • ref 属性:字符串类型,用来指示当前的参数所引用的 bean,也可以通过 <ref bean='...'/> 形式指定。
    • value 属性:字符串类型,用来指示当前的参数引用的值,也可以通过 <value>...<value/> 形式指定。

下面是一个使用实例,

    <!-- 使用属性进行赋值 -->
    <bean id="universal2" class="me.shouheng.spring.universal.UniversalBean">
        <constructor-arg name="hiTo" value="Spring"/>
    </bean>
    <!-- 或者使用下面这种方式 -->
    <bean id="hello" class="me.shouheng.spring.hello.beanimp.HelloApiImpl">
        <constructor-arg name="value">
            <value>My simple value.</value>
        </constructor-arg>
    </bean>

显然,constructor-arg 标签的 indextypename 属性用来指定当前的参数是构造函数中的哪一个。而 refvalue 用来指定当前参数的值。refvalue 只是refvalue 标签的一个补充。除了使用属性来直指定,我们还可以使用更加强大的子标签的形式来为构造函数的参数赋值。它的子标签包括 bean, ref, idref, value, null, array, list, set, mapprops,分别对应各种不同的数据类型。它们与 property 标签支持的类型基本一致,稍后我们会进行说明。

  • property 标签:用来对类的属性进行注入,这要求该类提供了该属性的 setter 方法。它提供的属性包括:
    • name 属性:字符串类型,用来指定当前构造函数的参数的名称。
    • ref 属性:字符串类型,用来指示当前属性所引用的 bean,也可以通过 <ref bean='...'/> 形式指定。
    • value 属性:字符串类型,用来指示属性的值,也可以通过 <value>...<value/> 形式指定。

显然,name 用来指定当前属性的名称,refvalue 用来指定属性的值。此外,还可以通过使用子元素来指定属性的值。它在 constructor-arg 标签支持的子元素的基础上增加了 meta 标签。稍后我们会进行说明。

  • qualifier 标签:即限定描述符,用于细粒度选择候选者。它有两个子标签,typevalue 分别用来指定候选的 Bean 的类型和值。

  • lookup-method 标签:它只有两个标签 namebean。用来使容器覆写指定的方法,并将 bean 属性指定的 bean 作为结果返回。比如

public interface Boss {
    Car haveCar();
}
<bean id="bmw" class="org.hope.spring.bean.lookup.Car" p:brand="奔驰GLC260" />
<bean id="boss" class="org.hope.spring.bean.lookup.Boss">
    <lookup-method name="haveCar" bean="bmw"/>
</bean>

此时使用 boss 实例的时候,调用 haveCar 方法将返回 bwm 对应的 bean。

  • replaced-method 标签:与上面的标签类似,只是用来替换 bean 中的某个方法。比如下面的实例中,用来将 yiJianLian 中的 onPlace() 方法替换为 yao。这里的 yao 不是一个普通的类,它需要实现 MethodReplacer 接口,其实就类似于代理模式的应用。
<bean id="yao" class="org.hope.spring.bean.replacedmethod.Yao">
</bean>
<bean id="yiJianLian" class="org.hope.spring.bean.replacedmethod.YiJianLian">
     <replaced-method name="onPlace" replacer="yao"/>
</bean>

4. 赋值标签

这里我们来梳理下上面提到的一系列的赋值标签:bean, ref, idref, value, null, array, list, set, mapprops。下面是一个基本的数据类型注入的例子,

    <bean id="hello" class="me.shouheng.spring.hello.beanimp.HelloApiImpl">
        <!-- 注入普通的字符串类型 -->
        <property name="string">
            <value>Simple String</value>
        </property>
        <!-- 注入数组类型 -->
        <property name="stringArray">
            <array value-type="java.lang.String">
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </array>
        </property>
        <!-- 注入列表类型 -->
        <property name="stringList">
            <list value-type="java.lang.String">
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
        <!-- 注入集合类型 -->
        <property name="stringSet">
            <set value-type="java.lang.String">
                <value>1</value>
                <value>2</value>
                <value>1</value>
            </set>
        </property>
        <!-- 注入哈希类型 -->
        <property name="stringMap">
            <map>
                <entry value-type="java.lang.String" value="1" key="1"/>
                <entry key="2" value="2"/>
            </map>
        </property>
    </bean>

2.2 XML 配置方式总结

2.2.1 获取 bean 实例的几种方式
  1. 通过 <bean> 标签和 constructor-arg 或者 propertry 标签初始化 bean;

  2. 通过通过静态工厂方法获取实例,即只通过 factory-method 指定。比如下面的例子中,这里要求 UniversalBean 类中包含一个静态的 staticFactory 工厂方法,并且工厂方法的参数是 hiTo1hiTo2

    <bean id="universal4" class="me.shouheng.spring.universal.UniversalBean" factory-method="staticFactory">
        <constructor-arg name="hiTo1" value="Spring"/>
        <constructor-arg name="hiTo2" value="Winter"/>
    </bean>
    
  3. 通过实例工厂方法获取实例:需要同时使用 factory-beanfactory-method 标签。以下面的程序为例,此时 FactoryBean 实例方法 factory 中包含两个参数 hiTo1hiTo2

    <bean id="factory" class="me.shouheng.spring.universal.FactoryBean"/>
    <bean id="universal5" factory-bean="factory" factory-method="factory">
        <constructor-arg name="hiTo1" value="Spring"/>
        <constructor-arg name="hiTo2" value="Winter"/>
    </bean>
    
2.2.2 p 命名空间

可以使用 p 命名空间来简化 setter 注入,比如上面的 refBean 可以使用如下的方式进行简化:

    <bean id="refBean" class="me.shouheng.spring.di.RefBean" p:diBean-ref="di"/>

注意这里需要引用 p 命名空间:

    xmlns:p="http://www.springframework.org/schema/p"

它的规则其实就是 p:字段名="值",如是字段是引用类型,那么就是 p:字段名-ref= “Bean 的 id”

2.2.3 循环依赖

所谓的循环依赖就是:A 创建的时候需要使用 B,B 需要用到 C,而 C 又要用到 A。按照注入的方式不同又分成:构造器循环依赖setter 方法循环依赖。构造器循环依赖表示 Bean 在创建的时候依赖于其他的 Bean 而造成的循环依赖,此种循环依赖无解,只能通过抛出 BeanCurrentlyInCreationException 异常表示循环依赖。对于 setter 方法循环依赖又分成两种情形:单例作用域的循环依赖prototype 作用域的循环依赖。前者是可以解决的,而后者无法解决。因为单例作用域的 Bean 在创建之后会被放在 Bean 创建池中待用,而 prototype 作用域的 Bean 不会被 Spring 容器缓存,无法提前暴露创建完毕的 Bean。

2.3 自动装配

2.3.1 基于 XML 的自动装配

所谓的自动装配,在 XML 中,就是指通过 XML 指定扫描的包之后,Spring 自动装载使用注解声明的 Bean. 它的使用非常简单,使用 context 命名空间中的 component-scan 来指定要扫描的包即可。

<!-- 注意,使用以上配置我们需要引用 context 命名空间,可以使用分隔符来指定多个扫描的包 -->
<context:component-scan base-package="me.shouheng.spring.componentscan"/>

默认地,它会扫描 @Component, @Repository, @Service, @Controller 注解声明的类,并将其加载到容器中。这四个注解可以使用各自的 value 字段指定该 Bean 的 id(默认将首字母小写之后作为 Bean 的名字)。这个几个注解分别用到下面的几种类型的类上面:

  1. @Component 通用的构造型注解,标识该类为 Spring 组件。
  2. @Controller 标识该类定义为 Spring MVC 控制器。
  3. @Repository 标识该类定义为数据仓库。
  4. @Service 标识该类定义为服务。

自动装配的时候,可以通过为字段添加 @Autowired 注解来实现,也可以不指定注解,但是要给字段提供 Setter 方法和构造方法。通常,建议使用基于构造方法的注入方式。@Autowired 注解有一个 required 的布尔类型字段,默认为 true,表示如果找不到可装配的 Bean 就抛异常;将其设置为 false 时,如果找不到也不会抛异常,但是如果最终没有注入值,又恰好用到了它,可能会在运行时抛出 NPE 异常。

关于 <context:annnotation-config><context:component-scan/> 标签的区别:如果用 <context:annotation-config/> ,我们还需要配置 Xml 注册 Bean,而使用 <context:component-scan /> 的话,注册的步骤都免了。当然前提是我们对需要扫描的类使用的注解(比如 @Componet, @Service 等),而如果同时使用两个配置的话,<context:annotation-config/> 会被忽略掉。就是说 <context:component-scan/> 的功能是包含 <context:annnotation-config> 的,前者不仅可以使用注解配置,还可以扫描自动包下面的 Bean。

2.3.2 基于注解的自动装配

当然,同样的功能你还可以通过使用基于类的配置方式实现。这里我们用 @Configurable 将其声明为一个配置类,然后使用 @ComponentScan 注解指定要扫描的包路径。这里的 @ComponentScan 注解与 XML 中的 component-scan 相似。

// 基于注解的自动装配
@Configurable
@ComponentScan(value = "me.shouheng.spring.componentscan")
public class ComponentScanConfiguration { 
}

// 通过如下的方式来获取一个上下文
AnnotationConfigApplicationContext context = 
    new AnnotationConfigApplicationContext(ComponentScanConfiguration.class);

2.4 基于 Java 配置

与基于注解自动扫描的方式不同的是,基于纯 Java 的配置方式中,只需要使用 @Configurable 注解即可。与在 XML 中不同的是,这种配置方式中你可以直接使用 Java 方法来生成 Bean 实例,并直接使用该实例的方法来为其赋值。因此,本质上讲,它只是把 XML 中的工作转换到了 Java 中进行处理。在定义 Bean 的方法之上使用 @Bean 注解即可将返回的类型作为一个 Bean 使用:

@Configuration
public class JavaConfig {

    @Bean("first")
    public FirstBean firstBean() {
        return new FirstBean(secondBean());
    }

    @Bean("second")
    public SecondBean secondBean() {
        return new SecondBean();
    }
}

2.5 混合使用多种配置方式

以上提供了基于 Java 和基于 XML 的两种配置方式,实际上我们可以混合使用多种不同类型的配置方式。这里我们简单列举一下好了:

  1. 在 XML 中引用基于 XML 配置:<import resource="AspectConfig.xml "/>
  2. 在 XML 中应用基于 Java 的配置:<bean class="me.shouheng.spring.javaconfig.JavaConfig"/>,没错就是将配置类当作 Bean 引入;
  3. 在基于 Java 的配置中引用基于 Java 的配置:@Import(value = {JavaConfig.class})
  4. 在基于 Java 的配置中引用基于 XML 的配置:@ImportResource(value = {"classpath:aop/AOPConfig.xml"})

总结

这篇文章总结了 Spring IoC 容器的一些基本的配置方式。其目的在于通过阅读了这篇文章之后,使读者能够了解 Spring 都提供了哪些 API,以便在使用的时候,能够使用它们来解决问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值