使用Spring管理Bean(一)

本文详细介绍了控制反转(IoC)和依赖注入(DI)的概念,以及在Spring框架中的实现,包括XML配置、构造器注入和属性注入,以及如何通过Spring管理Bean的生命周期和依赖关系,以及如何处理集合注入。
摘要由CSDN通过智能技术生成

一、IOC和DI

1、简介

IOC是Inversion Of Control(控制反转)的缩写,它是一种设计思想,是指将对象的控制权由程序代码反转给外部容器。

public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao;
    public AccoutServiceImpl( {
        this.accountDao = new AccountDaolmpl(); //在Spring中看不到这条语句[new AccountDaolmpl()]
    }
}

在Spring 中,控制反转是实现Spring容器的指导思想。有了Spring容器,开发人员无需编写管理对象生命周期依赖关系的代码,此项工作将由Spring容器根据配置自动完成,如此一来,对象的控制权由程序代码反转给Spring容器。

DI是Dependency Injection(依赖注入)的缩写,它是控制反转的另一种说法,同时也为控制反转提供了实现方法。依赖注入是指调用类对其他类的依赖关系由容器注入,这就避免了调用类对其他类的过度依赖,降低了类与类之间的耦合。注意,降低类与类之间的耦合度并不是让他们不再依赖,而是使得调用类不依赖具体的某个类的对象。

传统方式中,如果一个类依赖另一个类,则必须在该类中new一个具体依赖类的对象,比如:

public class AccountServiceImpl implements IAccountService {
    private AccountDaoImpl accountDao;
    public AccoutServiceImpl() {
        accountDao = new AccountDaoImpl(); 
    }
}

以上代码中,AccoutDaoImpl是 IAccountDao接口的具体实现类,当需要换接口的另一种实现时,代码需要进行相应改变:

private AccountDaoImpl2 accountDao;
accountDao = new AccountDaoImpl2();

实际开发中类与类之间依赖应该做到:编译期不依赖,运行时才依赖。

编译期依赖如下:

public class AccountServiceImpl implements IAccountService {
    private AccountDaoImpl accountDao;
    public AccoutServiceImpl(){
        this.accountDao = new AccountDaoImpl();
    }
}

运行时依赖如下:

AccoutServiceImpl类定义里,不再依赖具体的IAccountDao接口的实现类。

如果代码中存在多处类对象的创建,当具体实现类改变时相应代码都需要修改。此外,类的对象可以有不同的作用域,传统的方式很难去实现不同的作用域,比如实现单例模式。

如果使用Spring,则依赖关系由IOC容器进行注入。

public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao;
    public void setAccountDao(IAccountDao accountDao){
        this.accountDao = accountDao;
    }
}

在AccountServiceImpl中,不再依赖具体的IAccountDao接口的实现类,只需要知道接口所定义的方法,调用该方法即可,这就降低AccountServiceImpl类与IAccountDao接口实现类的耦合度。

XML定义如下:

<bean id="accountServiceImpl" class="cn.edu.hnit.example.AccountServiceImpl">
    <property name ="accountDao" ref="accountDaoImpl"/>
</bean>
<bean id="accountDaoImpl" class="cn.edu.hnit.example.AccountDaoImpl">
</bean>

对于依赖IAccountDao接口的类,只需要分别在XML中具体指定依赖即可,比如:

<bean id="accountServiceImpl" class="cn.edu.hnit.example.AccountServiceImpl">
    <property name ="accountDao" ref="accountDaoImpl"/>
</bean>
<bean id="accountDaoImpl" class="cn.edu.hnit.example.AccountDaoImpl2">
</bean>

AccountServiceImpl类依赖IAccountDao接口的实现类,而此时接口实现类已从AccountDaoImpl改成AccountDaoImpl2。

2、依赖注入的方式

依赖注入常用的两种方式为:

  • 构造器注入:将依赖对象以构造器参数的形式注入。
  • 属性注入:将依赖对象通过Setter方法注入。

 基于构造器函数的依赖注入需要在XML中指明依赖关系,比如TextEditor 需要依赖SpellChecker类时,XML的定义如下:

在TextEditor类中定义带参构造器。

public class TextEditor{
    private SpellChecker spellChecker;
    public TextEditor(SpellChecker spellChecker){
        this.spellChecker = spellChecker;
    }
}

基于setter 函数的依赖注入实际类似于给Bean设置值,因此需要有对应的setter方法,然后在XML中定义好Bean的值,比如:

public class TextEditor {
    private SpellChecker spellChecker;
    public void setSpellChecker(SpellChecker spellChecker){
        System.out.println("Inside setSpellChecker." );
        this.spellChecker = spellChecker;
    }
}
<bean id="textEditor" class="com.tutorialspoint.TextEditor">
    <property name="spellChecker" ref="spell"/>
</bean>
<bean id="spell" class="com.tutorialspoint.SpellChecker">
</bean>

注意:首先将构造方法设置为无参的构造方法,然后才能利用setter注入为其设置新的值。

基本数据类型的传递使用value对象的传递使用ref

public class TextEditor {
    private SpellChecker spellChecker;
    private String msg;
}

<bean id="textEditor" class="com.tutorialspoint.TextEditor">
    <property name="spellChecker" ref="spell"/>
    <property name = "language" value="english"/>
</bean>
<bean id="spell" class="com.tutorialspoint.SpellChecker">
</bean>

二、Bean的配置 

  1、Bean的定义

Bean是一个被实例化组装、并通过Spring loC容器所管理的对象。Bean由容器提供的配置元数据创建。在配置元数据中必须提供以下信息:

  • 如何创建一个bean
  • Bean的生命周期的详细信息
  • Bean的依赖关系

 通常使用XML文件来实现Bean的配置。XML配置文件的根元素是<beans>,<beans>元素中有很多<bean>子元素,每个<bean>子元素都定义了一个Bean,并且描述了该Bean应该被如何配置到Spring容器中。

<bean>元素提供了一系列属性用于描述Bean的信息:

  • class:指定用于创建bean的类的全限定名。
  • id:指定唯一的bean标识符。
  • scope:指定由特定bean定义创建的对象的作用域。
  • lazy-init:是否延时加载(需要使用时(getBean())才加载),默认为false。
  • init-method:指定对象初始化方法
  • destroy-method:指定对象销毁方法

<bean>元素包含配置依赖的子元素,子元素中基本数据类型的传递使用属性value,对象的传递使用属性ref。
<property>:用于通过属性注入的方式设置值。

public class TextEditor {
    private SpellChecker spellChecker;
    public void setSpellChecker(SpellChecker spellChecker){
        this.spellChecker = spellChecker;
    }
}
<bean id="textEditor" class="com.tutorialspoint.TextEditor">
    <property name="spellChecker" ref="spellChecker"/> <!-- name为唯一标识,必不可少 -->
</bean>

 <contrustor-arg>:用于自动寻找Bean的构造函数,并在初始化时将设置的参数注入。

<bean id="textEditor" class="cpm.tutorialspoint.TextEditor">
    <constructor-ag rer="spenChecker"/>
</bean>
<bean id="textEditor" class="com.tutorialspoint.TextEditor">
    <constructor-arg name = "spellChecher" ref="spellChecker"/>
</bean>

注意:<contrustor-arg>可以省略name的指定,但参数声明的顺序必须严格与构造器参数的顺序保持一致。而当指明name时,则不需遵照构造器参数的顺序。

Spring提供Bean定义继承机制,子Bean定义可以继承父定义的配置数据,也可以重写一些值或者添加其他值。
使用父属性(parent)来指定父Bean作为该属性的值,从而表示子Bean的定义。

class HelloWorld {
    private String messagel;
    private String message2;
}
class HelloIndia extends HelloWorld {
    private String message3;
}
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
    <property name="message1" value="Hello World!"/>
    <property name="message2" value="Hello Second World!"/>
</bean>
<bean id="helloIndia" class="com.tutorialspoint.HelloIndia" parent="helloWorld">
    <property name="message1" value="Hello India!"/> <!-- 重写 -->
    <property name="message3" value="Namaste India!"/> <!-- 添加 -->
</bean>

2、注入集合

Spring 可以传递Java Collection类型List,Set,Array,Map和Properties。集合类型的传递需要使用下面Spring提供的五个标签:

  • <list>:它可以注入一列值,允许重复。
    <property name="addressList">
        <list>
            <ref bean="address1"/>
            <ref bean="address2"/>
            <value>Pakistan</value>
        </list>
    </property>
    
  • <set>:它可以注入一组值,但不能重复。
    <property name="addressSet">
        <set>
            <ref bean="address1"/>
            <ref bean="address2"/>
            <value>Pakistan</value>
        </set>
    </property>
    
  • <array>:它可以注入一列值,允许重复。
    <property name="addressArray">
        <array>
            <ref bean="address1">
            <ref bean="address2">
            <value>Pakistan</value>
        </array>
    </property>
    
  • <map>:它可以用来注入名称-值对的集合,其中名称和值可以是任何类型。
    <property name="addressMap">
        <map>
            <entry key="one" value="INDIA">
            <entry key ="two" value-ref="address1"/>
            <entry key ="three" value-ref="address2"/>
        </map>
    </property>
    
  • <props>:它可以用来注入名称-值对的集合,其中名称和值都是字符串类型。
    <property name="addressProp">
        <props>
            <prop key="one">INDIA</prop>
            <prop key="two">Pakistan</prop>
            <prop key="three">USA</prop>
            <prop key="four">USA</prop>
        </props>
    </property>

对于基本数据类型,使用<value>元素或value属性,对于对象,使用<ref>元素或者ref。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值