Spring配置文件详解
2017-09-21 22:59
302 查看
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 4000 时会自动调用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:
如果Bean实现了DisposableBean接口,调用其destory()方法执行清理资源等工作。
如果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年龄是10 init 执行 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 的配置文件中,注入的Resou
d0de
rce资源总是由一个字符串来表示的,我们无需关心底层的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的查找简化为几行配置文件。
相关文章推荐
- 详解Spring的配置文件
- Spring之AOP配置文件详解
- 6.2.3 Spring 2.5配置文件详解
- spring配置详解-加载资源文件(转http://hi.baidu.com/pj19830204/blog/item/e27cdc511f020a2f43a75bd5.html)
- 详解Spring的配置文件
- spring配置文件详解(模版本)
- 详解Spring的配置文件
- Spring-配置文件Bean定义中parent属性详解
- 详解spring配置文件
- Spring配置文件详解
- 详解spring配置文件
- spring 框架配置文件详解
- Spring-配置文件Bean定义中parent属性详解
- Spring配置文件详解
- struts+hibernate+spring整合的文件配置详解
- spring配置文件详解(模版本)
- 详解Spring的配置文件
- spring配置文件详解
- 详解Spring的配置文件
- Spring配置文件详解