Spring IOC容器之进阶篇
来源:互联网 发布:淘宝阿里医生在哪里 编辑:程序博客网 时间:2024/05/17 01:09
上一篇博客介绍了一些IOC容器的基础,这里总结一下,IOC容器的数据类型转化和代码复用的一个策略。
一、自定义数据类型转化器:
类似Struts的数据类型的转化,诸如,java.util.Date类型的数据,如果使用Spring的容器注入,进行赋值,那么就需要自定义转换器,并集成到Spring的框架中。
1、在Bean类中设置Date类型字段的set方法:
private Date dateValue;public Date getDateValue() {return dateValue;}public void setDateValue(Date dateValue) {this.dateValue = dateValue;}
2、自定义Date格式转换器的java类:
UtilDatePropertyEditor需要继承PropertyEditorSupport:
public class UtilDatePropertyEditor extends PropertyEditorSupport {//将转换格式做成可配的private String pattern;@SuppressWarnings("unused")@Overridepublic void setAsText(String text) throws IllegalArgumentException {System.out.println("--------UtilDatePropertyEditor.setAsText() ----"+text);try {//日期转化Date date = new SimpleDateFormat(pattern).parse(text);this.setValue(date);} catch (ParseException e) {e.printStackTrace();throw new IllegalArgumentException(text);}}public void setPattern(String pattern) {this.pattern = pattern;}}
说明:
为了让自定义转化器支持客户自定义的格式,这里使用变量的方式,交给用户在配置文件中自定义类型。另外,这个类要继承PropertyEditorSupport,需要使用this.setValue(date);将转换后的日期交给容器。
3、将定义的转换器,配置到容器中,集成到容器中:
将自定义的配置单独放到一个配置文件(applicationContext-editor.xml)中:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean id="customEditors" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date"> <bean class="com.bjpowernode.spring.UtilDatePropertyEditor"> <property name="pattern" value="yyyy-MM-dd"></property> </bean> </entry> </map> </property> </bean> </beans>
自定义转换器的配置和普通bean的配置类似,也使用bean标签,因为其他的类不会调用自定义的转换器,所以这里就将转换器做为一种内部bean配置到了org.springframework.beans.factory.config.CustomEditorConfigurer类的内部。
也可以为自定义的转换器提供外部访问的接口:
<bean id="customEditors" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date" value-ref="customDatePropertyConvertor"> </entry> </map> </property> </bean> <!-- 外部可以使用这个转换器 --> <bean id="customDatePropertyConvertor" class="com.bjpowernode.spring.UtilDatePropertyEditor"> <property name="pattern" value="yyyy-MM-dd"></property> </bean>
不过这样做的意义不大,通常我们都会使用第一种配置方法。
4、使用容器为Date类型字段赋值:
上面的准备工作都做好后,就可以像普通的数据类型一样,为日期类型数据赋值注入,下面是applicationContext-beans.xml
<bean id="bean1" class="com.bjpowernode.spring.Bean1"><property name="map"><map><entry key="k1" value="v1"></entry><entry key="k2" value="v2"></entry></map></property><property name="dateValue"><value> 2013-09-28</value></property></bean>
类似Hibernate的Component映射,Spring也提供了一些代码复用的机制。如果有多个Bean有公共的属性字段,那么就可以将这些字段单独抽离出,放到一个类中,让其他类来复用这块儿代码即可。
如:Bean3和Bean4都有id、name和sex属性字段,且数据类型也都一样,那么就可以这样配置:
1、将公共属性放到一个抽象bean中,为了管理的方便,这里单独放到applicationContext-common.xml文件中:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"><bean abstract="true" id="abstractbean" name="beancommon"><property name="id" value="111" /><property name="name" value="任我行" /><property name="sex" value="男" /></bean><bean id="bean3" class="com.bjpowernode.spring.Bean3" parent="abstractbean" /></beans>
<bean id="bean4" class="com.bjpowernode.spring.Bean4" parent="abstractbean"><property name="age" value="25" /></bean>
Spring的配置文件可以有多个,也可以有一个,不管有多少个,即使在不同的配置文件中,所有的bean的id都必须是唯一的,所以,Bean4的这段代码可以放到applicationContext-common.xml文件中也可以放到applicationContext-beans.xml文件中。
如果Bean2对Bean3和Bean4都有引用,那么可以像使用其他Bean一样进行配置:
<bean id="bean2" class="com.bjpowernode.spring.Bean2"><property name="bean3" ref="bean3" /><property name="bean4" ref="bean4" /><property name="bean5" ref="bean5" /></bean>
三、Ioc容器对配置文件的读取支持:
Spring支持对单个配置问价的读取,也支持对配置文件数组的读取,同时也支持若干文件的读取,但是文件命名需要有一定的规律。
//读取配置文件数组//String[] xmlFiles= new String[]{"applicationContext-beans.xml","applicationContext-editor.xml"};//BeanFactory factory= new ClassPathXmlApplicationContext(xmlFiles);//读取单个配置文件//BeanFactory factory= new ClassPathXmlApplicationContext("applicationContext.xml");//读取以applicationContext-开头命名的配置文件BeanFactory factory= new ClassPathXmlApplicationContext("applicationContext-*.xml");
有了上面的基础和配置,就可以对程序进行测试访问了:
public class InjectionTest extends TestCase {//工厂是线程安全的BeanFactory factory ;/** *类似servlet的初始化,只初始化一次 *在这里了放置工厂信息 */@Overrideprotected void setUp() throws Exception {System.out.println("------Factory Init");//读取配置文件数组//String[] xmlFiles= new String[]{"applicationContext-beans.xml","applicationContext-editor.xml"};//BeanFactory factory= new ClassPathXmlApplicationContext(xmlFiles);//读取单个配置文件//BeanFactory factory= new ClassPathXmlApplicationContext("applicationContext.xml");//读取以applicationContext-开头命名的配置文件factory= new ClassPathXmlApplicationContext("applicationContext-*.xml");}/** * 这里销毁工厂信息 */@Overrideprotected void tearDown() throws Exception {}public void testInjection1() {////这里必须从容器中取出,不能使用new,类似jndi的查找,否则,不会读出相关的配置Bean2 bean2 = (Bean2)factory.getBean("bean2");System.out.println("bean2.bean3.id=" + bean2.getBean3().getId());System.out.println("bean2.bean3.name=" + bean2.getBean3().getName());System.out.println("bean2.bean3.sex=" + bean2.getBean3().getSex());System.out.println("bean2.bean4.id=" + bean2.getBean4().getId());System.out.println("bean2.bean4.name=" + bean2.getBean4().getName());System.out.println("bean2.bean4.sex=" + bean2.getBean4().getSex());System.out.println("bean2.bean4.age=" + bean2.getBean4().getAge());System.out.println("bean2.bean5.password=" + bean2.getBean5().getPassword());}}
setUp()类似Servlet的初始化,只进行一次初始化,如果希望一些变量和工厂在程序推出的时候销毁可以放到tearDown()方法中进行处理。
五、关于Scope:
Scope标签可以决定不同用户的Bean是否是同一个实例,故名思议,Scope是作用域范围的意思,它的常见的赋值有singleton和prototype。如果是prototype,我们可以理解成Bean的作用域仅限于每一个用户,而singleton则是所有用户共想用一个Bean实例。
我们可以使用下面的程序进行简单的测试:
public void testInjection1(){//这里必须从容器中取出,不能使用new,类似jndi的查找,否则,不会读出相关的配置Bean1 bean1 = (Bean1)factory.getBean("bean1");Bean1 bean2 = (Bean1)factory.getBean("bean1");System.out.println(bean1==bean2);}
六、自动装配:
Spring提供了两种自动装配的方式:byType和byName。
byName:在配置文件中给bean的id取名和引用它的类中的get和set方法同名,并设置即可自动加载。
byType:根据Bean类中,属性的数据类型,自动加载。
如,Bean2中有对Bean3、4、5的引用,并设置的相关的get、set方法:
public class Bean2 {private Bean3 bean3;private Bean4 bean4;private Bean5 bean5;public Bean3 getBean3() {return bean3;}public void setBean3(Bean3 bean3) {this.bean3 = bean3;}public Bean4 getBean4() {return bean4;}public void setBean4(Bean4 bean4) {this.bean4 = bean4;}public Bean5 getBean5() {return bean5;}public void setBean5(Bean5 bean5) {this.bean5 = bean5;}}
如果使用byType自动装配:
在xsi:schemaLocation约束中添加:default-autowire="byType",在对Bean2的配置中就无需手动显示添加注入:
<bean id="bean2" class="com.bjpowernode.spring.Bean2" /><bean id="bean33" class="com.bjpowernode.spring.Bean3">……</bean> <bean id="bean44" class="com.bjpowernode.spring.Bean4">……</bean><bean id="bean55" class="com.bjpowernode.spring.Bean5">……</bean>
如果是byName: default-autowire="byName" 要求其他的bean的id受Bean2中的方法名的约束:
<bean id="bean2" class="com.bjpowernode.spring.Bean2" /><bean id="bean3" class="com.bjpowernode.spring.Bean3">……</bean> <bean id="bean4" class="com.bjpowernode.spring.Bean4">……</bean><bean id="bean5" class="com.bjpowernode.spring.Bean5">……</bean>
七、总结:
Spring的Ioc容器对对象的注入提供了强大的支持,程序的灵活性往往都是通过对配置文件做活的,控制反转的思想很重要,在设计程序的时候应该借鉴这种设计思路。
Ioc容器提供了多种读取配置文件的方式,另外,对对象的装载也提供了一些自动的默认机制,这种做法也是值得学习和借鉴的。
Ioc还有一些其他的内容,如 default-lazy-init标签,BeanFactory、ApplicationContext等类和接口,这里就不再一一赘述。
- Spring IOC容器之进阶篇
- Spring之IoC容器
- spring之ioc容器
- Spring之IOC容器
- Spring IOC容器之基础篇
- spring详细进阶之IOC
- Spring之核心容器IoC
- Spring之IOC容器注入
- Spring 之IOC容器(初级)
- spring-mvc之ioc容器
- spring学习之IOC容器
- spring入门之IOC容器
- 【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)
- 【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)
- 【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)
- 【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)
- (二)spring 之IOC容器
- Spring之IOC容器解读系列-准备
- 【算法】图论_树_LCA
- Storm入门教程 第三章 Storm安装部署步骤
- Mvc示例代码之四Razor模板(二)
- Linux GPIO简介
- 【算法】图论_网络流_费用流
- Spring IOC容器之进阶篇
- java发展史
- 这样投简历,HR一定会看
- hdu4111 Alice and Bob
- Power(int base, int exponent) 函数实现
- BackTrack 5 R3 install OpenVAS 6
- 【分享】Windows个性美化方案
- Parameters: Character decoding failed解决办法
- html5 学习笔记 API canvas1 绘制对角线