Spring中属性注入详解

本文演示了int、String、数组、list、set、map、Date等属性的注入。
其中Date类型的注入则是借助了Spring提供的属性编辑器来实现的,首先是用到的五个实体类

package com.jadyer.model;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 * 常见属性的注入
 * @see 包括int,String,Array,list,set,map,Date的注入
 */
public class Bean11 {
  private Integer intValue;
  private String strValue;
  private String[] arrayValue;
  private List listValue;
  private Set setValue;
  private Map mapValue;
  private Date dateValue;
  /* 七个属性的setter和getter略 */
} 

package com.jadyer.model;
public class Bean22 {
  private Bean33 bean33;
  private Bean44 bean4422; //注入:与属性名无关,与setBean44()有关
  private Bean55 bean55;
  /* 三个属性的setter和getter略 */
} 

package com.jadyer.model;
public class Bean33 {
  private Integer id;
  private String name;
  private String sex;
  /* 三个属性的setter和getter略 */
} 

package com.jadyer.model;
public class Bean44 {
  private Integer id;
  private String name;
  private String sex;
  private Integer age;
  /* 四个属性的setter和getter略 */
} 

package com.jadyer.model;
public class Bean55 {
  private String password;
  /* 关于password的setter和getter略 */
} 

然后是我们自定义的java.util.Date类型转换器

package com.jadyer.util; 

import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; 

/**
 * java.util.Date属性编辑器。相当于类型转换器。这里是将String转为Date型
 * @see ----------------------------------------------------------------------------------------
 * @see 该示例主要让大家知道Spring也有这种机制,不是让大家以后写属性编辑器
 * @see 需要写属性编辑器的几率太少了,只要知道Spring也有类似的机制就可以了
 * @see ----------------------------------------------------------------------------------------
 * @see 所谓的属性编辑器,就是将Spring配置文件中的字符串转换成相应的Java对象
 * @see Spring内置了一些属性编辑器,也可以自定义属性编辑器
 * @see 自定义属性编辑器事,须继承PropertyEditorSupport类并覆写setAsText()方法
 * @see 最后再将自定义的属性编辑器注入到Spring中,即可
 * @see ----------------------------------------------------------------------------------------
 */
public class UtilDatePropertyEditor extends PropertyEditorSupport {
  private String pattern; //将转换的格式放到配置文件中,让Spring注入进来
  public void setPattern(String pattern) {
    this.pattern = pattern;
  } 

  @Override
  public void setAsText(String text) throws IllegalArgumentException {
    System.out.println("======UtilDatePropertyEditor.setAsText()======" + text);
    try {
      Date date = new SimpleDateFormat(pattern).parse(text);
      this.setValue(date); //注意:这里放进去的是一个java.util.Date对象,故输出的时间是默认的格式
    } catch (ParseException e) {
      e.printStackTrace();
      throw new IllegalArgumentException(text); //继续向上抛参数非法的异常
    }
  }
} 

用到的针对所有实体类的applicationContext-beans.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.5.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
      default-lazy-init="true">
  <!-- default-lazy-init="true"属性的说明,详见InjectionTest.java类的第49行 -->
  <!-- default-autowire="byName或byType",这是Spri0ng提供的自动装配bean的两种方式byName和byType,详解略 --> 

  <!-- ***********************【LAZY====延迟初始化】*********************************************************************** -->
  <!-- 执行testInjection22()时默认的会输出======UtilDatePropertyEditor.setAsText()======2010年06月04日 -->
  <!-- 即此时并未设置default-lazy-init="true",这说明Bean11中的dateValue属性的值被注入了 -->
  <!-- 事实上,默认的Spring在创建ApplicationContext时,会将配置文件中所有的对象实例化并进行注入 -->
  <!-- 这样做的好处是如果Spring配置文件中的某些配置写错了,它立刻就能检测出来 -->
  <!-- 而Struts1.X的配置文件,如果某个类写错了,是不会出问题的,只有在真正执行的时候,才会出问题 -->
  <!-- 对于Spring而言,也可以采用相关的属性延迟配置文件的初始化,即default-lazy-init="true" -->
  <!-- 即只有真正使用的时候,再去New这个对象,再为属性注入。这时就涉及到LAZY,即延迟初始化 -->
  <!-- 只需修改Spring配置文件即可,如<beans xsi:schemaLocation="http://www...." default-lazy-init="true"> -->
  <!-- 这时的作用范围即整个配置文件,同理也可对各个<bean>标签的lazy-init属性进行单独配置 -->
  <!-- 但一般都不会这么设置,而是在BeanFactory创建的时候,即完成注入,这样也便于检查出错误 -->
  <!-- ***************************************************************************************************************** --> 

  <bean id="bean11" class="com.jadyer.model.Bean11">
    <property name="intValue" value="123"/><!-- 注入时,字符串123会自动转换为int型 -->
    <property name="strValue" value="Hello_Spring"/>
    <property name="arrayValue">
      <list>
        <value>array11</value>
        <value>array22</value>
      </list>
    </property>
    <property name="listValue">
      <list>
        <value>list11</value>
        <value>list22</value>
      </list>
    </property>
    <property name="setValue">
      <set>
        <value>set11</value>
        <value>set22</value>
      </set>
    </property>
    <property name="mapValue">
      <map>
        <entry key="key11" value="value11"/>
        <entry key="key22" value="value22"/>
      </map>
    </property>
    <property name="dateValue" value="2010年06月04日"/><!-- 这里Date格式应与applicationContext-editor.xml配置的相同 -->
  </bean> 

  <bean id="bean22" class="com.jadyer.model.Bean22">
    <property name="bean33" ref="bean33"/>
    <property name="bean44" ref="bean44"/>
    <property name="bean55" ref="bean55"/>
  </bean> 

  <bean id="bean55" class="com.jadyer.model.Bean55">
    <property name="password" value="123"/>
  </bean>
</beans> 

用到的针对公共实体类的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.5.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 

  <!-- 利用抽象bean提取出公共配置 -->
  <!-- 首先指定<bean>标签的abstract属性为true,然后在其它<bean>中指定其parent即可 -->
  <bean id="AbstractBean" abstract="true">
    <property name="id" value="2"/>
    <property name="name" value="张起灵"/>
    <property name="sex" value="男"/>
  </bean>
  <bean id="bean33" class="com.jadyer.model.Bean33" parent="AbstractBean"/>
  <bean id="bean44" class="com.jadyer.model.Bean44" parent="AbstractBean">
    <property name="age" value="26"/>
  </bean>
</beans> 

<!-- 使用AbstractBean之前的bean33和bean44的原形如下 -->
<!--
<bean id="bean33" class="com.jadyer.model.Bean33">
  <property name="id" value="100"/>
  <property name="name" value="张三"/>
  <property name="sex" value="男"/>
</bean>
<bean id="bean44" class="com.jadyer.model.Bean44">
  <property name="id" value="100"/>
  <property name="name" value="张三"/>
  <property name="sex" value="男"/>
  <property name="age" value="90"/>
</bean>
 --> 

用到的针对java.util.Date属性编辑器的applicationContext-editor.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.5.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 

  <bean id="utilDatePropertyEditor" class="com.jadyer.util.UtilDatePropertyEditor">
    <property name="pattern" value="yyyy年MM月dd日"/>
  </bean> 

  <!-- 查看源码得知,在CustomEditorConfigurer类的131行提供了一个setCustomEditors方法,所以就能够注入了 -->
  <bean id="customEditors" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="customEditors">
      <map>
        <entry key="java.util.Date" value-ref="utilDatePropertyEditor"/>
      </map>
    </property>
  </bean>
</beans> 

<!-- 也可以使用内部<bean>把utilDatePropertyEditor写在内部 -->
<!-- 这样就只有它自己有权使用了,外部就无法使用了 -->
<!-- 由于不提供外界访问,所以内部<bean>没有id属性 -->
<!-- 示例如下 -->
<!--
<bean id="customEditors" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="customEditors">
    <map>
      <entry key="java.util.Date">
        <bean class="com.jadyer.util.UtilDatePropertyEditor">
          <property name="pattern" value="yyyy年MM月dd日"/>
        </bean>
      </entry>
    </map>
  </property>
</bean>
 -->

最后是使用JUnit3.8写的单元测试类

package com.jadyer.junit; 

import junit.framework.TestCase; 

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; 

import com.jadyer.model.Bean11;
import com.jadyer.model.Bean22; 

public class PropertyInjectionTest extends TestCase {
  private ApplicationContext factory; 

  @Override
  protected void setUp() throws Exception {
    /****====读取单一的配置文件====****/
    //factory = new ClassPathXmlApplicationContext("applicationContext.xml"); 

    /****====利用数组读取多个配置文件====****/
    //这样就会把两个配置文件作为一个来使用,表面上看是作为两个使用的
    //其实内部是作为一个使用的,所以在多个配置文件中,里面的id不能重复
    //但是name属性可以重复,就好像人的身份证编号和名字的区别是一样的
    //String[] configLocations = new String[]{"applicationContext.xml", "applicationContext-editor.xml"};
    //factory = new ClassPathXmlApplicationContext(configLocations); 

    /****=====利用 * 匹配模式读取多个配置文件====****/
    //业界流行的一句话:约定优于配置
    //所以说当有了一个统一的比较好的约定之后,就可以利用框架提供的功能,减少配置量
    //另外:如果没有读取到applicationContext-*.xml,此时即便存在applicationContext.xml,它也不会读的
    factory = new ClassPathXmlApplicationContext("applicationContext-*.xml");
  } 

  /**
   * 该方法演示的是常见属性的注入,包括int,String,Array,list,set,map,Date的注入
   * @see 其中Date类型的注入则是借助了Spring属性编辑器来实现的
   */
  public void testInjection11() {
    //Bean11 bean11 = new Bean11(); //若简单的new,那么它的属性是不会被注入的。注入的前提必须是从IoC容器中拿出来的,才会注入
    Bean11 bean11 = (Bean11)factory.getBean("bean11"); //此时bean11就是从IoC容器中获取到的,所以它的依赖就会被全部注入
    System.out.println("bean11.intValue=" + bean11.getIntValue());
    System.out.println("bean11.strValue=" + bean11.getStrValue());
    System.out.println("bean11.arrayValue=" + bean11.getArrayValue());
    System.out.println("bean11.listValue=" + bean11.getListValue());
    System.out.println("bean11.setValue=" + bean11.getSetValue());
    System.out.println("bean11.mapValue=" + bean11.getMapValue());
    System.out.println("bean11.dateValue=" + bean11.getDateValue());
  } 

  /**
   * 该方法主要演示的是将公共的配置进行抽象,以减少配置量
   */
  public void testInjection22() {
    Bean22 bean22 = (Bean22)factory.getBean("bean22");
    System.out.println("bean22.bean33.id=" + bean22.getBean33().getId());
    System.out.println("bean22.bean33.name=" + bean22.getBean33().getName());
    System.out.println("bean22.bean33.sex=" + bean22.getBean33().getSex());
    System.out.println("bean22.bean44.id=" + bean22.getBean44().getId());
    System.out.println("bean22.bean44.name=" + bean22.getBean44().getName());
    System.out.println("bean22.bean44.sex=" + bean22.getBean44().getSex());
    System.out.println("bean22.bean44.age=" + bean22.getBean44().getAge());
    System.out.println("bean22.bean55.password=" + bean22.getBean55().getPassword());
  }
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 实例讲解Java的Spring框架中的控制反转和依赖注入

    近来总是接触到 IoC(Inversion of Control,控制反转).DI(Dependency Injection,依赖注入)等编程原则或者模式,而这些是著名 Java 框架 Spring.Struts 等的核心所在.针对此查了 Wikipedia 中各个条目,并从图书馆借来相关书籍,阅读后有些理解,现结合书中的讲解以及自己的加工整理如下: eg1 问题描述: 开发一个能够按照不同要求生成Excel或 PDF 格式的报表的系统,例如日报表.月报表等等.   解决方案: 根据"面向接口编

  • Java的Spring框架中bean的继承与内部bean的注入

    bean的定义继承 bean定义可以包含很多的配置信息,包括构造函数的参数,属性值,比如初始化方法,静态工厂方法名等容器的具体信息. 子bean定义从父定义继承配置数据.子的定义可以覆盖一些值,或者根据需要添加其他. Spring bean定义继承无关,与Java类的继承,但继承的概念是一样的.你可以定义一个父bean定义为模板和其他孩子bean可以从父bean继承所需的配置. 当使用基于XML的配置元数据,指明一个子bean定义使用所在的当前属性指定的父bean作为这个属性的值. 例如: 让我

  • 深入解析Java的Spring框架中bean的依赖注入

    每一个基于java的应用程序都有一个共同工作来展示给用户看到的内容作为工作的应用几个对象.当编写一个复杂的Java应用程序,应用程序类应该尽可能独立其他Java类来增加重复使用这些类,并独立于其他类别的测试它们,而这样做单元测试的可能性.依赖注入(或有时称为布线)有助于粘合这些类在一起,同时保持他们的独立. 考虑有其中有一个文本编辑器组件的应用程序,要提供拼写检查.标准的代码将看起来像这样: public class TextEditor { private SpellChecker spell

  • 详析Spring中依赖注入的三种方式

    前言 平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是"控制反转",通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做. 在Sprin

  • JavaWeb Spring依赖注入深入学习

    一.依赖注入(DI) 依赖注入听起来很高深的样子,其实白话就是:给属性赋值.一共有两种方法,第一是以构造器参数的形式,另外一种就是以setting方法的形式. 1 构造器注入 1 使用构造器注入 使用xml的注入方式 A. 通过参数的顺序 <constructor-arg index="0"><value>张三</value></constructor-arg> <constructor-arg index="1"

  • Spring不能注入Static变量的原因及Spring注入静态变量

    下面给大家介绍spring不能注入static变量的原因,具体详情如下所示: Spring 依赖注入 是依赖 set方法 set方法是 是普通的对象方法 static变量是类的属性 @Autowired private static JdbcTemplate jdbcTemplate; 单纯看这个注入过程是没有报错的,但是在接下来的jdbcTemplate.query()会报空指针错误. ps:Spring注入静态变量 今天碰到一个问题,我的一个工具类提供了几种静态方法,静态方法需要另外一个类的

  • 详解Java Spring各种依赖注入注解的区别

    注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.Service.Controller.Repository.Component. Autowired是自动注入,自动从spring的上下文找到合适的bean来注入 Resource用来指定名称注入 Qualifier和Autowired配合使用,指定bean的名称 Service,Controller,Repository分别标记类是Service层类,Contro

  • Spring注入方式有哪些

    在Spring配置文件中使用XML文件进行配置,实际上是让Spring执行了相应的代码,例如: 使用<bean>元素,实际上是让Spring执行无参或有参构造器 使用<property>元素,实际上是让Spring执行一次setter方法 但Java程序还可能有其他类型的语句:调用getter方法.调用普通方法.访问类或对象的Field等,而Spring也为这种语句提供了对应的配置语法: 调用getter方法:使用PropertyPathFactoryBean 调用类或对象的Fil

  • 详解Java的Spring框架中bean的注入集合

    使用value属性和使用<property>标签的ref属性在你的bean配置文件中的对象引用,这两种情况下可以处理单值到一个bean,如果你想通过多元值,如Java Collection类型List, Set, Map 及 Properties.要处理这种情况,Spring提供了四种类型的如下集合的配置元素: 可以使用<list> 或<set> 来连接任何实现java.util.Collection或数组. 会遇到两种情况(a)将收集的直接的值及(b)传递一个bean

  • 详解Java的MyBatis框架与Spring框架整合中的映射器注入

    MyBatis-Spring允许你在Service Bean中注入映射器.当使用映射器时,就像调用DAO那样来调用映射器就可以了,但是此时你就不需要进行任何DAO实现的编码,因为MyBatis会为你进行. 使用注入的映射器,你的代码就不会出现任何MyBatis-Spring依赖和MyBatis依赖.在我们的应用中有这样一个简单的映射器.你也应该知道映射器仅仅是一个接口: public interface UserMapper { User getUser(String userId); } 这是

随机推荐