Spring配置文件详解

来源:互联网 发布:赌博游戏源码 编辑:程序博客网 时间:2024/06/05 02:23

1、 关于applicationContext.xml文件开头

DTD验证XML配置文件

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"        "http://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans><!-- bean definitions here --></beans>

另一种Schema验证配置文件:

<?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 definitions here --></beans>

这个可以去spring-framework-4.3.6.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html里找到 ,里面有很多配置信息

2、实例化Spring的IoC容器

2.1、使用BeanFactory

Spring的BeanFactory采用的是工厂模式,实现了BeanFactory接口的类负责创建并配置所有的Bean。应用程序将Bean的创建和配置完全委托给BeanFactory,然后从BeanFactory获取并使用它们。

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));//在调用getBean("beanId")方法请求Bean的实例时,才调用相应的初始化方法

2. 2、使用ApplicationContext

ApplicationContext 本质上仍然是一个BeanFactory,因为ApplicationContext是从BeanFactory 继承而来的。不过,ApplicationContext 提供了更多的功能,并能够与一些应用环境整合。

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        //context = new FileSystemXmlApplicationContext("");        //context = new XmlWebApplicationContext();//实例化ApplicationContext时会自动调用Bean指定的初始化方法,

3 Bean 初始化

ApplicationContext 初始化Bean和基本的BeanFactory有所不同,基本的BeanFactory总是延迟加载Bean,直到第一次调用getBean(“beanId”)方法请求Bean的实例时,BeanFactory才会创建这个Bean,而ApplicationContext 在自身初始化时就一次性创建了所有的Bean。因此,ApplicationContext在初始化时就能验证XML配置文件的正确性,而使用基本的BeanFactory,直到调用getBean(“BeanId”)方法获取Bean实例时,才可能会发现配置错误而导致抛出异常。

3.1 Bean的初始化流程

1.容器根据XML配置文件中Bean的定义实例化一个Bean,并传入必要的构造方法参数。
2.容器根据XML配置文件使用依赖注入设置Bean的属性。
3 如果Bean实现了BeanNameAware接口,调用其setBeanName()方法。
4 如果Bean实现了BeanClassLoaderAware接口,调用其setBeanClassLoader()方法。
5.如果Bean实现了BeanFactoryAware接口,调用其setBeanFactory()方法。
6.如果使用ApplicationContext 并且Bean实现了ResourceLoaderAware接口,调用其setResourceLoader()方法。
7.如果使用ApplicationContext 并且Bean实现了ApplicationEventPublisherAware接口,调用其setApplicationEventPublisher()方法。
8.如果使用ApplicationContext 并且Bean实现了MessageSourceAware接口,调用其setMessageSource()方法。
9.如果使用ApplicationContext 并且Bean实现了ApplicationContextAware接口,调用其setApplicationContext()方法。
10.如果使用WebApplicationContext 并且Bean实现了ServletContextAware接口,调用其setServletContext()方法,仅对web程序有效。
//上述通过实现特有接口,传入给Bean相应的实例,以便使用。
11.如果关联了BeanPostProcessor,调用BeanPostProcessor的postProcessBeforeInitialization()方法。
12.如果Bean实现了InitializingBean接口,调用其afterPropertiesSet()方法执行一些初始化工作。
该初始化工作会发生在XML配置文件设置Bean属性之后,即会覆盖依赖注入的值。
13.如果Bean定义了init-method方法,调用这个方法执行一些初始化工作。
该初始化方法也一样。
14.如果关联了BeanPostProcessor,调用BeanPostProcessor的postProcessAfterInitialization()方法。

容器关闭时,会销毁已创建的Bean:

  1. 如果Bean实现了DisposableBean接口,调用其destory()方法执行清理资源等工作。
  2. 如果Bean定义了destory-method方法,调用这个方法执行资源清理等工作。

    以下代码展示了一些XML文件的配置以及接口的使用:

package com.bean;import org.springframework.beans.factory.InitializingBean;public class ChineseImpl implements Person,InitializingBean{    private String name;    private int age;    @Override    public void speak() {        // TODO Auto-generated method stub        System.out.println(this.name+"年龄是"+this.age);    }    public String getName() {        return name;    }    public int getAge() {        return age;    }    public void setName(String name) {        this.name = name;    }    public void setAge(int age) {        this.age = age;    }    @Override    public void afterPropertiesSet() throws Exception {        // TODO Auto-generated method stub        this.name="afterPropertiesSet";        this.age = 10;        System.out.println("afterPropertiesSet()执行");    }}package com.bean;public class AmericanImpl implements Person {    private String name;    private int age;    @Override    public void speak() {        // TODO Auto-generated method stub        System.out.println(this.name + "年龄:"+this.age);    }    public String getName() {        return name;    }    public int getAge() {        return age;    }    public void setName(String name) {        this.name = name;    }    public void setAge(int age) {        this.age = age;    }    public void init(){        this.name="init";        this.age=13;        System.out.println("init 执行");    }}//配置文件<bean id="chinese" class="com.bean.ChineseImpl">        <property name="name" value="小明"></property>        <property name="age" value="23"></property>    </bean>    <!-- init-method指定无参数的初始化方法(通过实现InitializingBean接口,Spring容器会自动调用afterPropertiesSet()方法执行初始化 -->    <bean id="american" class="com.bean.AmericanImpl" init-method="init">        <property name="name" value="托尼"></property>        <property name="age" value="24"></property>     </bean>//运行package com.test;import javax.swing.plaf.basic.BasicIconFactory;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.xml.XmlBeanFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;import org.springframework.core.io.ClassPathResource;import org.springframework.web.context.support.XmlWebApplicationContext;import com.bean.AmericanImpl;import com.bean.Person;public class Test {    public static void main(String[] args) {        // TODO Auto-generated method stub        //ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        //context = new FileSystemXmlApplicationContext("");        //context = new XmlWebApplicationContext();        BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));        Person person = (Person)bf.getBean("chinese");        person.speak();        person= (AmericanImpl) bf.getBean("american");        person.speak();    }}//运行结果:afterPropertiesSet()执行afterPropertiesSet年龄是10init 执行init年龄:13

4 装配Bean

4.1 注入基本类型

如上代码所示

4.2 注入引用类型

//新增Book类package com.bean;public class Book {    private String bookName;    private String author;    public String getBookName() {        return bookName;    }    public String getAuthor() {        return author;    }    public void setBookName(String bookName) {        this.bookName = bookName;    }    public void setAuthor(String author) {        this.author = author;    }}//在AmericanImpl类中添加下列代码private Book book;public void setBook(Book book){    this.book = book;}//修改配置文件的部分Bean<bean id="american" class="com.bean.AmericanImpl" init-method="init">        <property name="name" value="托尼"></property>        <property name="age" value="24"></property>         <property name="book" ref="book"></property>    </bean>    <bean id="book" class="com.bean.Book">        <property name="bookName"><value>书名</value></property>    </bean>

4.3 注入null

//修改配置文件的部分Bean配置<bean id="american" class="com.bean.AmericanImpl" init-method="init">        <property name="name" value="托尼"></property>        <property name="age" value="24"></property>         <property name="book" ><null></null></property>    </bean>

4.4 注入集合类型

//配置如下,其它集合类似(可以混合使用<value><ref>节点),必须和集合或数组的类型相符。<property name="book" >    <list>        <value></value>        <ref></ref>    </list></property>

在使用上诉集合类型时,要注意注入属性的参数使用接口而非具体类,列如,使用List而非ArrayList,这样才能保证Spring能正确地注入,这也符合针对抽象编程的原则。
public void setXxx(List Xxx){} //可以引入泛型,Spring会做强制的转型

4.5 注入Resource资源

除了基本类型、引用类型和集合类型之外,在应用程序中还经常使用各种资源。Java的标准库提供了File、URL、InputStream等常用的资源类型,但是这些资源无法方便地注入到Bean中,因此,Spring提供了一个更强大,更方便的访问底层资源的Resource抽象接口,大大简化了在Bean中注入各种Resource。
在Spring 的配置文件中,注入的Resource资源总是由一个字符串来表示的,我们无需关心底层的Resource究竟是何种具体类型。事实上,Spring根据字符串来判断应该如何创建相应的Resource。
从字符串到Resource的转化规则:

前缀 说明 示例 classpath: 从ClassPath加载该资源 classpath:config.xml http: 作为URL加载该资源 http://java.sun.com/ file: 作为URL加载该文件资源 file:///c:/WINDOWS/ 无 根据具体的ApplicationContext text.txt

5 构造方法注入

构造方法的参数是强制注入的,相比属性注入,这样可以保证Bean在创建时被正确地初始化了。属性可能由于多次注入而导致不正确的状态。

public AmericanImpl(String name,int age){    this.name=name;    this.age = age;}<bean id="am" class="com.bean.AmericanImpl">    <constructor-arg value="constructor"> </constructor-arg>    <constructor-arg value="5"></constructor-arg></bean>//如果有class="com.bean.AmericanImpl"的其它Bean打算采取设置注入,应再写一个默认的构造函数//public AmericanImpl(){}

6 Bean的作用域

Bean的作用域定义了Bean的生命周期,通过配置文件的智能提醒(scope=”“)可以看到,一共定义了4种作用域:prototype、request、session和singleton。如果不指定scope,默认值是scope=”singleton”。

6.1 Singleton 作用域

Spring的容器仅为每个Bean创建一个实例并保持Bean的引用,意思是,每次调用getBean()方法请求某一个Bean时,Spring总是返回相同的Bean实例。因此,每个Bean有且仅有一个实例。

6.2 prototype 作用域

每次返回Bean的新实例。因此,Spring容器一旦将实例交给客户端,就不再对其跟踪引用,所以无法对prototype作用域的Bean定义destory-method。

7 配置工厂Bean

当我们使用Spring的IoC容器管理Bean时,Spring容器就相当于一个复杂的工厂,它负责根据XML配置文件创建并配置Bean。很多时候,我们需要使用自己的工 厂对象来创建Bean,如果将这一功能也交给Spring容器,Spring管理的就不是普通的Bean实例,而是”工厂“实例。我们把Spring管理的”工厂“实例暂且称为”工厂Bean“。此时,应用程序调用getBean()方法时,Spring返回的不是直接创建的Bean的实例,而是工厂Bean创建的Bean实例。
在Spirng中,可以定义三种不同类型的工厂Bean。下面分别讲解3种工厂Bean的配置。

7.1 使用静态工厂

对象的创建被委托给工厂类的一个静态方法:

public class StaticFactoryBean{    public static Integer createRandom(){        return new Integer(new Random().nextInt());    }}

如果直接使用这个静态工厂,典型的Java代码:
Integer rnd = StaticFactoryBean.createRandom();
如果将其纳入Spring容器来管理,需要通过factory-method指定静态方法名称。

<bean id="random" class="com.bean.StaticFactoryBean" factory-method="createRandom"></bean>

调用getBean(“random”)返回的便是静态工厂方法产生的随机数。(若需要每次返回不同的随机数,指定scope=”prototype”即可)

7.2 使用实例工厂

通过实例工厂创建一个对象时,必须首先实例化工厂对象,然后才能调用工厂对象的成员方法,这往往是因为对象的创建还依赖于工厂实例的内部状态。

public class InstanceFactoryBean{    private String format="yy-MM-dd HH:mm:ss";    public void setFormat(String format){        this.format = format;    }    public  String createTime(){        return new SimpleDateFormat(format).format(new Date());    }}

定义实例工厂需要分别定义两个Bean。

<bean id="instanceFactoryBean" calss="com.action.InstanceFactoryBean">    <property name="format" value="yyyy-MM-dd HH:mm:ss" /></bean><bean id ="currentTime" factory-bean="instanceFactoryBean" factory-method="createTime"></bean>

7.3 实现FactoryBean接口

隐式地使用一个工厂Bean实例,该Bean实现了Spring专有的org.springframework.beans.factory.FactoryBean接口。

package com.bean;import org.springframework.beans.factory.FactoryBean;public class AmericanImpl implements Person,FactoryBean<Book> {    @Override    public Book getObject() throws Exception {        // TODO Auto-generated method stub        return new Book();    }    @Override    public Class<?> getObjectType() {        // TODO Auto-generated method stub        return Book.class;    }    @Override    public boolean isSingleton() {        // TODO Auto-generated method stub        return false;    }}//定义这个Bean和普通的Bean没有区别:<bean id="bo" class="com.action.AmericanImpl" />

然而,一旦某个Bean实现了FactoryBean接口,这个Bean就不能再被作为普通Bean使用。Spring的IoC容器会自动地检测,调用getBean(“bo”)返回的将不是AmericanImpl的实例,而是它的工厂方法getObject()返回的Book对象实例。
要获得AmericanImpl的实例,可以用getBean(“&bo”)返回的便是工厂实例。
‘&’符号只能用于实现了FactoryBean接口的工厂Bean。

7.4 常用的FactoryBean

JndiObjectFactoryBean

JndiObjectFactoryBean用于获取指定的JNDI对象,唯一需要指定的是jndiName属性。
<bean id=systemStartTime" class="org.springframework.jndi.JndiObjectFactoryBean">    <property name="jndiName" value="java:comp/env/systemStartTime" /></bean>public class Test {    public static void main(String[] args) throws Exception {        // TODO Auto-generated method stub        bindJndi();        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");        System.out.println(context.getBean("systemStartTime"));    }    //启动一个基于RMI的JNDI服务并绑定一个Date对象。    private static void bindJndi() throws Exception{        //启动RMI;        LocateRegistry.createRegistry(1099);        //设置JNDI环境        System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");        System.setProperty(Context.PROVIDER_URL, "rmi://localhost:1099");        //拓展Date实现Remote接口:        class RemoteDate extends Date implements Remote{}; //使用RMI的JNDI对绑定对象有所限制,被绑定对象必须实现Remote接口        //绑定至JNDI:        InitialContext ctx = new InitialContext();        ctx.bind("java:comp/env/systemStartTime", new RemoteDate());        ctx.close();    }}//使用传统的方式去获得一个JNDI对象private static Object jndiLookup(){    InitialContext ctx = null;    try {        ctx = new InitialContext();        return ctx.lookup("java:comp/env/systemStartTime");    } catch (NamingException e) {            // TODO Auto-generated catch block            throw new RuntimeException();    }finally{        if(ctx!=null)        try {            ctx.close();        } catch (NamingException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }   }

通过Spring容器,我们将JNDI的查找简化为几行配置文件。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 22岁的儿子在家不说话怎么办 儿子2周4个月了不说话怎么办 三岁的宝宝还不会数数怎么办 2岁宝宝晚上不睡觉不听话怎么办 8个月的狗狗怕人不敢出门怎么办 狗太怕人了怎么办都不敢出门 媳妇和婆婆晚上都不想带孩子怎么办 婆婆和媳妇带孩子观念不一样怎么办 婆婆给媳妇买了不喜欢的家具怎么办 断奶后宝宝对奶粉很抗拒怎么办 两岁宝宝断奶不喝奶粉怎么办 宝宝两岁了断奶后奶粉不吃怎么办 宝宝断奶两天了不愿意吃奶粉怎么办 一岁四个月宝宝断奶不喝奶粉怎么办 四个月宝宝断奶不喝奶粉怎么办 四个月宝宝断奶后不吃奶粉怎么办 2岁的宝宝不开口说话怎么办 一周岁宝宝断奶不喝奶粉怎么办 八个月宝宝断奶不喝奶粉怎么办 婆家人总是用心机对待娘家人怎么办 婆婆老是背后说我娘家人坏话怎么办 婆家姐带孩子住娘家不走怎么办? 老是想在娘家不想回婆家怎么办 娘家和婆家同时向我借钱怎么办 土地确权后娘家婆家都没有怎么办 结了婚婆家向娘家借钱怎么办? 婆婆的娘家人从我家住怎么办 八个月宝宝断奶后不吃奶粉怎么办 吃母乳的宝宝不吸奶嘴怎么办 宝宝吸了奶嘴不吸母乳怎么办 婴儿吃了奶嘴不吸母乳怎么办 十一个月宝宝断奶不喝奶粉怎么办 孩子三门成绩全不及格家长该怎么办 宝宝快十个月了还不会爬怎么办 小孩写字老把手向里扭曲怎么办 孩子该上四年级了数学差的很怎么办 孩子上三年级了数学成绩好差怎么办 三年级数学老考70-80分怎么办 叛逆期的孩子用死来威胁家长怎么办 叛逆期的孩子抽烟喝酒家长该怎么办 大学遇到不好的老师加课怎么办