spring学习笔记2——基本Bean配置

来源:互联网 发布:电视如何进入网络电视 编辑:程序博客网 时间:2024/06/05 08:12

BeanFactory介绍
    正如其名字所暗示的,Bean工厂采用了工厂设计模式。就是说,这个类负责创建和分发Bean。在Spring中有几种BeanFactory的实现。其中最常用的是org.springframework.beans.factory.xml.XmlBeanFactory,她根据XML文件中的定义装在Bean。
    要创建XmlBeanFactory,学要传递一个org.springframework.core.io.Resource实例给构造函数。此Resource对象提供XML文件工厂。Spring提供了有应的Resource实现。如下表所示:
Resource实现目的org.springframework.core.io.ByteArrayResource定义内容由一组字节给定的资源org.springframework.core.io.ClassPathResource定义可从classpath提取的资源org.springframework.core.io.DescruptiveResource定义包含资源描述符但是实际没有可读资源的资源org.springframework.core.io.FileSystemResource定义可从文件系统提取的资源org.springframework.core.io.InputStreamResource定义可从输入流提取的资源org.springframework.web.portlet.context.PortletContextResource定义可用在portlet上下文中的资源org.springframework.web.context.support.ServletContextResource定义可用在servlet上下文中的资源org.springframework.core.io.UrlResource定义可从给定URL提取的资源

例如下面的代码使用一个FileSystemResource来创建一个XmlBeanFactouy,其中Bean的定义来自文件系统中的XML文件:
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("c:/beans.xml"));
MyBean myBean = (MyBean)factory.getBean("myBean");

使用应用上下文:
    BeanFactory对简单的应用来说已经很好了,但是为了获得Spring框架的强大功能,你需要使用Spring的更加高级的容器——应用上下文。
    表面上ApplicationContextBeanFactory差不多。两者都是载入Bean定义信息,装配Bean,根据需要分发Bean。但是ApplicationContext提供了更多功能:
  • 文本信息解析工具,包括对国际化(I18N)的支持。
  • 提供了载入文件资源的通用方法,如载入图片。
  • 可以向注册为监听去的Bean发送事件。

ApplicationContext的诸多实现中欧冠,有三个实现经常用到:
  • ClassPathXmlApplicationcContext——从类路径中的XML文件载入上下文定义信息,把上下文定义文件当成类路径资源。
  • FileSystemXmlApplicationContext——从文件系统中的XML文件载入上下文定义信息。
  • XmlWebApplicationContext——从Web系统中的XML文件载入下上文定义信息。

    基于Web的Spring中要介绍XmlWebApplicationContext,这里简单的介绍ClassPathXmlApplicationcContextFileSystemXmlApplicationContext,如下面代码所示:
ApplicationContext ctx = new FileSystemXmlApplicationContext("foo.xml");
ApplicationContext ctx = new ClassPathXmlApplicationContext("foo.xml");
    它俩的区别是FileSystemXmlApplicationContext只能从指定的路径中寻找foo.xml文件,而ClassPathXmlApplicationContext可以在整个类路径(包括jar文件)中寻找foo,xml文件。无论哪种实现使用getBean()方法获取Bean。

创建Bean
生命一个接口:
public interface Performer {
    void perform() throws PerformanceException;
}


创建一个简单的Bean
package com.springinaction.springidol;

public class Juggler implements Performer {
    private int beanBags = 3;
    
    public Juggler() {}

    public juggler(int beanBags) {
        this.beanBags = beanBags;
    }

    public void perform() throws PerformanceException {
        System.out.println("JUGGLING" + beanBags + "BEANBAGS"):
    }
}

下面是在Spring配置文件中如何配置的:
<bean id="duke" class="com.springinaction.springidol.Juggler" />

通过构造函数注入:
<bean id="duke" class="com.springinaction.springidol.Juggler">
    <constructor-arg value="15" />
</bean>

注入Bean属性
public interface Instrument {
    void play();
}
public class Saxophone implements Instrument {
    public Saxophone() {}

    public void play() {
        System.out.println("TOOT TOOT TOOT");
    }
}
publci class Instrumentalist implement Performer {
    public Instrumentalist() {}

    public void perform() throws PerformanceException {
        System.out.print("Playing" + song + ":");
        instrument.play();
    }

    private  int age;
    public void setSong(int age) {
        this.age= age;
    }

    private  String song;
    public void setSong(String song) {
        this.song = song;
    }

    private  Instrument instrument;
    public void setInstrument (Instrument instrument) {
        this.instrument= instrument;
    }
}

<bean id="instrument" class="com.springinaction.springidol.Saxophone" />
<bean id="kenny" class="com.springinaction.springidol.Instrumentalist">
    <property name="age" value="37" />
    <property name="song" value="Jingle Bells" />
    <property name="instrument" value="instrument" />
</bean>

装配集合:
package org.spring.beans.collection;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

public class OneManBand implements Performer {
    public OneManBand(){}
    
    public void perform() {
        System.out.println("---------------List--------------------");
        for(Instrument instrument : instruments){
            instrument.play();
        }
        System.out.println("---------------Set--------------------");
        for(Instrument instrument : instruments2){
            instrument.play();
        }
        System.out.println("---------------Map--------------------");
        for(String key : instruments3.keySet()){
            System.out.print(key+" : ");
            Instrument instrument = instruments3.get(key);
            instrument.play();
        }
        System.out.println("------------Properties----------------");
        for(Iterator iter = instruments4.keySet().iterator();iter.hasNext();){
            String key = (String)iter.next();
            System.out.println(key+" : " + instruments4.getProperty(key));
        }
    }

    private Collection<Instrument> instruments;
    public void setInstruments(Collection<Instrument> instruments) {
        this.instruments = instruments;
    }

    private Collection<Instrument> instruments2;
    public void setInstruments2(Collection<Instrument> instruments2) {
        this.instruments2 = instruments2;
    }

    private Map<String,Instrument> instruments3;
    public void setInstruments3(Map<String,Instrument> instruments3) {
        this.instruments3 = instruments3;
    }

    private Properties instruments4;
    public void setInstruments4(Properties instruments4) {
        this.instruments4 = instruments4;
    }
}


collection.xml配置文件:
<bean id="Hank" class="org.spring.beans.collection.OneManBand">
    <property name="instruments">
        <list>
            <ref bean="guitar"/>
            <ref bean="cymbal"/>
            <ref bean="harmonica" />
        </list>
    </property>
    <property name="instruments2">
        <set>
            <ref bean="guitar"/>
            <ref bean="cymbal"/>
            <ref bean="harmonica" />
            <ref bean="harmonica" />
        </set>
    </property>
    <property name="instruments3">
        <map>
            <entry key="GUITAR" value-ref="guitar" />
            <entry key="CYMBAL" value-ref="cymbal" />
            <entry key="HARMONICA" value-ref="harmonica" />
        </map>
    </property>
    <property name="instruments4">
        <props>
            <prop key="GUITAR">STRUM STRUM STRUM</prop>
            <prop key="CYMBAL">CRASH CRASH CRASH</prop>
            <prop key="HARMONICA">HUM HUM HUM</prop>
        </props>
    </property>
</bean>

<bean id="guitar" class="org.spring.beans.collection.Saxophone">
    <property name="str" value="STRUM STRUM STRUM" />
</bean>

<bean id="cymbal" class="org.spring.beans.collection.Saxophone">
    <property name="str" value="CRASH CRASH CRASH" />
</bean>

<bean id="harmonica" class="org.spring.beans.collection.Saxophone">
    <constructor-arg value="HUM HUM HUM"></constructor-arg>
</bean>

public class CollectionApp {
    public static void main(String[] args){
        ApplicationContext ctx = new     ClassPathXmlApplicationContext("org/spring/beans/collection/collection.xml");
        Performer performer = (Performer)ctx.getBean("Hank");
        performer.perform();
    }
}


自动装配:Spring提供了四种自动装配类型:
  • byName——试图在容器中寻找和需要自动装配的属性名相同的Bean(或ID)。如果没有找到相符的Bean,这个属性就没有被装配上。
  • byType——试图在容器中寻找一个与需要自动配置的属性类型相同的Bean,如果没有找到相符的Bean,这个属性就没有被装配。如果找到超过一个相符的Bean,会抛出org.springframework.bans.factory.UnsatisfiedDependencyException异常。
  • constructor——试图在容器中查找与需要自动装配的Bean的构造函数参数一致的一个或多个Bean,如果存在不确定bean或构造函数,容器会抛出异常org.springframework.bans.factory.UnsatisfiedDependencyException。
  • autodetect——首先尝试使用constructor来自动装配,然后使用byType方式,不确定性的处理与constructor方式和byType方式一样。

Bean范围化:
    当在Spring中生命<bean>时,有声明Bean范围的选项。为了湿的每次都能产生一个新的Bean实例,可以声明Bean的scope属性为prototype。例如:
<bean id="saxophone" class="org.spring.beans.collection.Saxophone" scope="prototype" />
    大部分情况保留范围化设置是默认的singleton,但是对于新的域对象实例,在使用Spring作为厂时,可能会使用prototype。
范围完成任务singleton定义Bean的范围为每个Spring容器一个实例(默认值)Prototype允许Bean可以被多次实例化(使用一次就创建一个)request定义Bean的范围是HTTP请求。只有使用有web能力的Spring上下文(例如Spring MVC)时才有效session定义Bean的范围是HTTP会话。只有使用有web能力的Spring上下文(例如Spring MVC)时才有效plobal-session定义Bean的范围是全局HTTP会话。只有在portlet上下文中才有效


利用工厂方法来创建Bean:
    很多时候,在Spring应用上下文中配置的Bean都可以通过调用类的构造函数来创建。当然,可以使用公共的构造函数来创建,但是如果想通过静态厂方法,使用第三方API来展现某些类型,该怎么做?Stage类是单例类的基本示例:
package org.spring.beans.controlbean;

public class Stage {
    private Stage() {}
    //简单的装在实例
    private static class StageSingletonHolder {
        static Stage instance = new Stage();
    }
    //返回实例
    public static Stage getInstance() {
        return StageSingletonHolder.instance;
    }
}

为了确保没有其他方法可以创建Stage的多个实例:
<bean id="theStage" class="org.spring.beans.controlbean.Stage" factory-method="getInstance" />

初始化和销毁Bean:创建一个Instrumentalist类,此类有初始化方法和销毁方法:
package org.spring.beans.controlbean;

public class Instrumentalist {

    private Instrument instrument;

    public Instrument getInstrument() {
        return instrument;
    }

    public void setInstrument(Instrument instrument) {
        this.instrument = instrument;
    }
    public void tuneInstrument() {
        instrument.tune();
    }
    public void cleanInstrument() {
        instrument.clean();
    }
}

    现在需要一个方法来确保在创建Instrumentalist时tuneInstrument()方法被调用,以及在销毁对象时会调用cleanInstrument()方法。为此在生命kenny Bean时...
<bean id="kenny" class="org.spring.beans.controlbean.Instrumentalist"
        init-method="tuneInstrument" destroy-method="cleanInstrument">
    <property name="instrument" ref="saxophone" />
</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-2.0.xsd"
        default-init-method="initInstrument"
        default-destroy-method="cleanInstrument">

</beans>

作为init-method和destroy-method的备选,我们还可以实现两个Spring接口InitializingBean和DisposableBean。

原创粉丝点击