`
hehebendan
  • 浏览: 81763 次
  • 性别: Icon_minigender_1
  • 来自: 伊拉克
社区版块
存档分类
最新评论

Spring中bean的配置

阅读更多
先从IOC说起,这个概念其实是从我们平常new一个对象的对立面来说的,我们平常使用对象的时候,一般都是直接使用关键字类new一个对象,那这样有什么坏处呢?其实很显然的,使用new那么就表示当前模块已经不知不觉的和new的对象耦合了,而我们通常都是更高层次的抽象模块调用底层的实现模块,这样也就产生了模块依赖于具体的实现,这样与我们JAVA中提倡的面向接口面向抽象编程是相冲突的,而且这样做也带来系统的模块架构问题。很简单的例子,我们在进行数据库操作的时候,总是业务层调用DAO层,当然我们的DAO一般都是会采用接口开发,这在一定程度上满足了松耦合,使业务逻辑层不依赖于具体的数据库DAO层。但是我们在使用的时候还是会new一个特定数据库的DAO层,这无形中也与特定的数据库绑定了,虽然我们可以使用抽象工厂模式来获取DAO实现类,但除非我们一次性把所有数据库的DAO写出来,否则在进行数据库迁移的时候我们还是得修改DAO工厂类。

    那我们使用IOC能达到什么呢?IOC,就是DAO接口的实现不再是业务逻辑层调用工厂类去获取,而是通过容器(比如spring)来自动的为我们的业务层设置DAO的实现类。这样整个过程就反过来,以前是我们业务层主动去获取DAO,而现在是DAO主动被设置到业务逻辑层中来了,这也就是反转控制的由来。通过IOC,我们就可以在不修改任何代码的情况下,无缝的实现数据库的换库迁移,当然前提还是必须得写一个实现特定数据库的DAO。我们把DAO普遍到更多的情况下,那么IOC就为我们带来更大的方便性,比如一个接口的多个实现,我们只需要配置一下就ok了,而不需要再一个个的写工厂来来获取了。这就是IOC为我们带来的模块的松耦合和应用的便利性。

    那为什么说IOC很简单呢?说白了其实就是由我们平常的new转成了使用反射来获取类的实例,相信任何人只要会用java的反射机制,那么自己写一个IOC框架也不是不可能的。比如:

……
public Object getInstance(String className) throws Exception
{
    Object obj = Class.forName(className).newInstance();
    Method[] methods = obj.getClass().getMethods();
    for (Method method : methods) {
        if (method.getName().intern() == "setString") {
            method.invoke(obj, "hello world!");
        }
    }
}
……

    上面的一个方法我们就很简单的使用了反射为指定的类的setString方法来设置一个hello world!字符串。其实可以看到IOC真的很简单,当然了IOC简单并不表示spring的IOC就简单,spring的IOC的功能强大就在于有一系列非常强大的配置文件维护类,它们可以维护spring配置文件中的各个类的关系,这才是spring的IOC真正强大的地方。在spring的Bean定义文件中,不仅可以为定义Bean设置属性,还支持Bean之间的继承、Bean的抽象和不同的获取方式等等功能。

在spring的Bean配置中总的来说其实就一个标签<bean></bean>,这个bean标签就攘括了几乎所有的配置,然后bean的继承、抽象等都是基于此标签之上的,掌握了bean的配置,详细可以使自己有一个比较大的提升,尤其是对于新手来说(我也是,呵呵  )。最基础的bean配置如下:

<bean id="bean_test" class="cn.qtone.test.HelloWorld"></bean>

    这里我们就简单的使用HelloWorld类来实例化,使用默认的构造方法,即相当于我们使用:

HelloWorld tmp = new HelloWorld();

    但有一点不同的是在spring配置中的在整个应用期间只有一个实例,即是单例的,当然这个单例是指对一个IOC容器(spring)来说的,而不是我们通常说说的单态模式。当然,spring也可以这样配置不是单态的实例,比如我们修改如下:

<bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype"></bean>

    注意其中的不同颜色部分,这样配置后就表明每次从spring容器中获取HelloWorld的实例的时候就会new一个新对象,即我们所说的原型,spring中scope默认的是单态(singleton),当然针对web应用程序,还可以配置为request、session等范围。至于什么时候使用什么权限范围就要看应用程序的使用了,比如在多线程程序中,单态是否会对程序有所影响就需要考虑了。

    如果HelloWorld类没有空的构造方法,只有如下的两个构造方法,那我们该如何配置呢?

……
public HelloWorld(String str)
{
    ……
}

public HelloWorld(Date date, int i)
{
    ……
}
……

    由于没有默认构造方法,所以我们就需要在bean的配置中写上构造参数才可以,如下:

<!-- 使用一个参数的构造 -->
<bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype">
    <constructor-arg><value>hello</value></constructor-arg>
</bean>

    上面说的使用一个参数的,即带字符串参数的构造方法,如果想使用带日期和整型的构造方法,那么就要做如下的配置了:

<bean id="bean_date" class="java.util.Date" />

<!-- 使用二个参数的构造 -->
<bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype">
    <constructor-arg ref="bean_date"></constructor-arg>
    <constructor-arg><value>345</value></constructor-arg>
</bean>

    注意到上面的配置中我们使用了ref关键字,这个是表示引用配置文件中的ID为bean_date的对象,另外对于类型,spring会做恰当的转换,比如将345转换成数字等。当然,这样对简单的构造来说不会有什么问题,如果情况比较复杂的话,那么一般建议使用序号来标定,如下:

<!-- 使用二个参数的构造 -->
<bean id="bean_test" class="cn.qtone.test.HelloWorld" scope="prototype">
    <constructor-arg index="0" ref="bean_date"></constructor-arg>
    <constructor-arg index="1"><value>345</value></constructor-arg>
</bean>

    这样,使用index属性表示该参数所在位置了后,无论是spring构造起来,还是我们查看都会很方便。当然,spring也提供了自动查找,也就是依赖查找的功能,但是这个我觉得大家还是少用,因为这样会使整个配置文件看起来非常的不直观,而且不清晰,说不定过了一段时间再去看的时候就不知道是什么意思了,在正式应用项目中,还是将各个bean的关系进行组织和编写清楚为好。

    上面所说的都是构造来实例化一个bean,但有时候我们都会使用工厂模式来获取bean。对于工厂模式,我们一般也使用静态工厂模式和实例工厂模式,这两个在spring中配置也是不太一样的。对于静态工厂模式来实例化bean的,我们的配置如下:

<bean id="bean_string" class="cn.qtone.test.TestFactory" factory-method="getBean"/>

    当然,我们也可以为静态工厂模式的bean来使用构造参数,这个就不说了。我们上面的bean配置对应的实际代码就应该是:

……
public static Object getBean()
{
    return "hello world";
}
……

    那么spring在实例化ID为bean_string的bean时,就会使用TestFactory的getBean()方法来获取,而且TestFactory是没有被实例化的,即是使用静态方法来获取的。对于实例工厂模式的话,我们的配置和上面就稍微有点不一样了,那我们就应该配置两个bean, 一个是实例的工厂bean,还一个就是我们要获取的bean的配置了,如下:

<bean id="bean_factory" class="cn.qtone.test.TestBeanFactory"/>

<bean id="bean_helloWorld" factory-bean="bean_factory" factory-method="getHello"/>

    上面的配置中,spring容器将首先实例化一个TestBeanFactory,然后再根据该类的方法getHello来获取一个bean的实例,我们这里以HelloWorld对象为例,对应的代码就应该如下:

……
public HelloWorld getHello()
{
    return new HelloWorld();
}
……

    注意到,我们这里的getHello方法并不是静态方法,而是实例方法,所以必须先实例化TestBeanFactory后才能够调用。

    上面说的都是如何去实例化一个bean,没有说到bean的属性注入。虽然我们也可以通过构造的时候进行一次注入,但这样做不仅失去了灵活性,而且一长串的构造参数看着也眼疼哈,呵呵。当然,有一种情况下,我们是应该使用构造注入的,就是希望注入的对象不能够被外界修改时,我们这时候就必须使用构造注入了。对于bean的属性注入,以HelloWorld为例,我们可以简单的配置如下:

<bean id="bean_test" class="cn.qtone.test.HelloWorld">
    <property name="hello" value="你好!" />
    <property name="world" value="世界" />
    <property name="date" ref="bean_date" />
</bean>

    上面的配置中使用了三个属性注入,即spring中的setter注入方式。注意第三个属性,使用了ref,表明这个date属性的设置参数是关联到ID为bean_date的bean上去的。注意在使用setter注入的时候,属性的名称不是方法的全名称,而是满足javaBean规范的命名方式,即如果属性名称为xxx,那么其对应的方法名称就应该是:setXxx(),注意的是除了xxx中第一个字符不区分大小写之外,其他的是要严格区分的。那么对照上面的配置,我们的HelloWorld的方法就应该如下:

……
public void setHello(String hello)
{
    ……
}

public void setWorld(String world)
{
    ……
}

public void setDate(Date date)
{
    ……
}
……

    使用setter注入的好处就是可以很清晰的知道每一个注入的是什么参数和意义,通过名称就可以很容易的看出来,这也是spring提倡使用setter注入的原因之一。
分享到:
评论

相关推荐

    spring bean XML配置入门

    在实际开发中,我们可以使用Eclipse的Spring插件来简化Bean配置的创建和管理,同时结合Maven来构建和运行Spring应用。 通过以上内容,你应该对Spring框架中的Bean XML配置有了初步的理解。掌握这些知识点后,你将...

    Spring的Bean配置

    在本文中,我们将深入探讨Spring中的Bean配置,包括IoC和DI的概念,Bean的配置方式,以及不同类型的IOC容器。 **Spring的Bean配置**: 在Spring中,Bean是应用中的对象,它们由Spring IoC容器负责创建、管理和装配...

    Spring的Bean配置说明

    ### Spring的Bean配置详解 #### 一、Spring配置文件根元素`&lt;beans&gt;`解析 - **功能概述**:`&lt;beans&gt;`是Spring配置文件的根元素,用来包含一个或多个`&lt;bean&gt;`元素,用于定义Spring容器管理的各种Bean。 #### 二、`...

    SPRING:bean配置properties

    本文将深入解析如何利用`PropertyPlaceholderConfigurer`进行bean配置的properties操作,包括单个properties文件的配置、多个properties文件的集成以及多个`PropertyPlaceholderConfigurer`的协同工作,旨在帮助...

    详解Spring 中如何控制2个bean中的初始化顺序

    Spring 中控制 2 个 bean 的初始化顺序 在 Spring 框架中,控制多个 bean 的初始化顺序是一个常见的问题。本篇文章将详细介绍如何控制 2 个 bean 的初始化顺序,提供了多种实现方式,并分析了每种方式的优缺。 ...

    spring的Bean配置说明

    以下是对Spring Bean配置的详细解释: 1. `&lt;beans&gt;` 根元素:这是Spring配置文件的起点,它包含了所有的Bean定义。Spring容器会解析这个文件并创建相应的Bean实例。 2. `&lt;bean&gt;` 元素:这是Spring配置中最常见的...

    详解Spring中Bean的生命周期和作用域及实现方式

    Spring中Bean的生命周期和作用域及实现方式 Spring是一个非常流行的Java应用程序框架,它提供了一个灵活的机制来管理Bean的生命周期和作用域。Bean的生命周期和作用域是Spring框架中两个非常重要的概念,它们决定了...

    在非spring注解类中使用spring容器中的bean_普通类中使用yml配置文件中的配置信息

    然而,在某些情况下,我们可能需要在非Spring注解的类中访问Spring容器中的Bean,或者在这些类中使用YAML配置文件中的配置信息。本篇将详细介绍如何在这样的场景下实现这一目标。 首先,让我们来理解如何在非Spring...

    spring中的bean

    1. **Bean的定义**:在XML配置中,我们可以使用`&lt;bean&gt;`标签来定义一个Bean,例如: ```xml &lt;bean id="myBean" class="com.example.MyClass"/&gt; ``` 这里的`id`属性是Bean的唯一标识,`class`属性指定Bean对应的Java...

    Spring Bean创建初始化流程.docx

    在Spring框架中,Bean的创建和初始化是IoC(Inversion of Control)容器的核心功能,这一过程涉及到多个...Spring的IoC容器使得应用更加灵活和易于测试,因为Bean的依赖关系可以通过配置来调整,而不是硬编码在代码中。

    Spring--2.Spring 中的 Bean 配置-4

    在Spring框架中,Bean配置是核心概念之一,它关乎到对象的创建、初始化、装配以及管理。本节我们将深入探讨Spring中的Bean配置,主要关注如何通过XML、注解以及Java配置方式来管理Bean。 首先,让我们从XML配置说起...

    spring bean的生命周期

    - **XML配置**:在传统的Spring应用中,Bean的定义通常写在XML配置文件中,如`springbean-xml`中的配置。 - **注解配置**:使用`@Component`,`@Service`,`@Repository`和`@Controller`注解标记类,配合`@...

    Spring定义bean的三种方式和自动注入

    在XML配置中,我们通常在`applicationContext.xml`文件中定义Bean。例如,对于`Student`和`Teacher`类,我们分别创建`bean`标签,并设置`id`属性作为Bean的唯一标识,`class`属性指定Bean对应的类。此外,通过`...

    Spring bean 动态注册,jar包热替换

    Spring bean 一般通过配置文件和注解进行加载,如果要实现jar或class文件,动态实现spring bean 的动态加载,并通过UrlClassLoader完成jar和class文件的加载。可以实现jar的热替换。spring的bean动态加载则需要对...

    创建SpringBean配置工具类

    创建SpringBean配置工具类(安全)如: &lt;bean id=... scope="prototype"&gt;&lt;/bean&gt;

    spring运行过程中动态注册bean

    在Spring框架中,动态注册Bean是一项非常实用的功能,它允许我们在应用运行时向Spring容器添加新的Bean定义。这种能力在很多场景下都是极其有用的,比如根据不同的环境配置加载不同的服务实现,或者在运行时根据某些...

    Spring项目bean基础配置代码

    现在,考虑到压缩包文件名称`spring_02_bean`,这可能是一个关于Spring Bean配置的代码示例或教程。在这样的资源中,你可能会找到如何在XML配置文件中声明Bean、设置别名以及指定作用范围的实际示例代码。通过阅读和...

    Spring--2.Spring 中的 Bean 配置-1

    在Spring框架中,Bean配置是核心概念之一,它关乎到对象的创建、初始化、依赖注入以及生命周期管理。本文将深入探讨Spring中的Bean配置,主要基于标题"Spring--2.Spring 中的 Bean 配置-1"及其相关的上下文。 首先...

Global site tag (gtag.js) - Google Analytics