Spring IoC 中的依赖注入(Dependency Injection)的两种实现方式。

本节主要讲解在 Spring IoC 中的依赖注入(Dependency Injection)的两种实现方式。

由于英文水平有限,同时为保证原汁原味地表达Spring中关于依赖注入部分本来的含义,标题和部分内容采用 Spring Framework 官方文档中的英文原文。

另外,在测试代码中读取 Spring 配置文件时,尽量使用了完整的路径而未使用通配符。

0、Field and Proprey
设存在以下 Java Bean :

public class Person {

private int id ;
private String name ;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

}
在 Person 类中,以成员变量(Member Variable)形式存在的 id 和 name 属于 Person 类中的字段( Field )。字段(Field)本质上是一个变量,用于存储数值(可以是基本数据类型的数值、也可以是引用)。

在 Person 类中刻意声明了两种不同类型的字段(Field):

private int id ;
private String name ;

因为id是基本数据类型,因此该字段(Field)可以直接存储整数值。

而name是 String 类型,属于引用类型,因此该字段(Field)用于存储字符串的引用。

注意:即使在为 String 类型的变量赋值时使用了字符串字面量,也不能改变String变量中存储的是引用的事实。

在 Java Bean 中,字段(Field)通常是私有的,因此需要提供setter和getter来访问相应的字段,比如在 Person 类中,就有以下方法用以访问 id 字段:

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

在这里,我们要通过getter或setter来强调属性(property)的概念。

对于 getter 来说,按照以下顺序进行变换即可得到属性(property):

将 getId 方法的方法名去除 get ,得到 Id (注意不改变任何字母的大小写)
将 第1步 中得到的字符串首字母变小写,得到 id (即得到属性名称)
同样对于 setter 来说,也可以按照以下顺序进行变换即可得到属性(property):

将 setId 方法的方法名去除 set ,得到 Id (注意不改变任何字母的大小写)
将 第1步 中得到的字符串首字母变小写,得到 id (即得到属性名称)
因为绝大多数的 Java Bean 中字段(field)名称 和 属性(property) 是相同的,因此很多人会误以为属性(property)就是字段(field)、字段(field)就是属性(property)。

为了进一步区分字段(field)和属性(property),我们将 Person 改成以下形式:

public class Person {

private int personId ;
private String personName ;

public int getId() {
    return personId;
}

public void setId(int id) {
    this.personId = id;
}

public String getName() {
    return personName;
}

public void setName(String name) {
    this.personName = name;
}

}
此时,成员变量 personId 和 personName 是 Person 类中的字段(field),用于存储数据。而 id 和 name 是 Person 类的属性(property),用于访问相应的字段。

因此在 JSP 中,可以通过以下形式的 EL 表达式中可以用以下形式来获取属性(property)值

id : ${person.id}
name : ${person.name}

本质上,是通过 getId 和 getName 来获取 personId 和 personName 字段的值。

接下来,我们提供一个 Java Bean 供后续使用:

package io.malajava.ioc.injection;

import java.util.Date;

public class Sinaean {

private Integer id ;
private String name ;
private char gender ;
private Date birthdate ;
private boolean married ;

public Sinaean() {
    super();
    System.out.println( "public Sinaean()" );
}

public Sinaean(Integer id, String name) {
    super();
    System.out.println( "public Sinaean(Integer,String) : " + id );
    this.id = id;
    this.name = name;
}

public Sinaean(Integer id, String name, char gender) {
    super();
    System.out.println( "public Sinaean(Integer,String,char) : " + id );
    this.id = id;
    this.name = name;
    this.gender = gender;
}

@Override
public String toString() {
    return "{" +
            "id : " + id +
            ", name : '" + name + '\'' +
            ", gender : " + gender +
            ", birthdate : [ " + birthdate +
            " ], married : " + married +
            '}';
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    System.out.println( "Sinaean # setId( Integer )" );
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    System.out.println( "Sinaean # setName( String )" );
    this.name = name;
}

public char getGender() {
    return gender;
}

public void setGender(char gender) {
    System.out.println( "Sinaean # setGender( char )" );
    this.gender = gender;
}

public Date getBirthdate() {
    return birthdate;
}

public void setBirthdate(Date birthdate) {
    System.out.println( "Sinaean # setBirthdate( java.util.Date )" );
    this.birthdate = birthdate;
}

public boolean isMarried() {
    return married;
}

public void setMarried(boolean married) {
    System.out.println( "Sinaean # setMarried( boolean )" );
    this.married = married;
}

}
1、Setter-based dependency injection
1.1、使用 标签实现注入
Java Bean
参见前面步骤中的 Sinaean 类
Configuration Metadata






    
    
    
    
    



    
    
    
    
    
        
            
            
            
        
    

注: 设以上内容存在于类路径下的 io/malajava/ioc/injection/injection-setter-property.xml 文件中。

注意,在以上配置中使用 标签可以为指定JavaBean的属性(property)注入属性值,其中:

标签的 name 属性用于指定 Java Bean 中属性的名称
标签的 value 属性用于指定 需要注入的属性值
标签的 ref 属性用于指定 引用其它的 bean
以下17种类型可以通过标签的 value 属性直接指定字面值:

Java语言中的 8 种基本数据类型
Java语言中 8 种基本数据类型对应的包装类类型
java.lang.String 类型
所有的引用类型(包括包装类类型和String类型)的属性,都可以使用 标签的 ref 属性来应用已经存在于IoC容器中的其它的 bean (同种类型),比如:



    
    
    



    
    

所有的引用类型(包括包装类类型和String类型)的属性,也都可以在标签内部使用 标签来创建需要注入的bean,比如:

Testing public class SetterInjectionTest1 {
public static void main(String[] args) {

    DateFormat df = new SimpleDateFormat( "yyyy-MM-dd" );

    // 指定 Configuration Metadata
    String configLocation = "classpath:io/malajava/ioc/injection/injection-setter-property.xml" ;

    // 创建 Spring IoC 容器
    ApplicationContext iocContainer = new ClassPathXmlApplicationContext( configLocation ) ;

    // 从容器中获取 bean
    Sinaean s = iocContainer.getBean( "xiaoyuer" , Sinaean.class );
    System.out.println( s ); // s.toString()
    System.out.println( df.format( s.getBirthdate() ) );

    Sinaean x = iocContainer.getBean( "huawuque" , Sinaean.class );
    System.out.println( x ); // x.toString()
    System.out.println( df.format( x.getBirthdate() ) );

}

}
1.2、使用 p 命名空间 实现注入
Java Bean
参见前面步骤中的 Sinaean 类
Configuration Metadata
从 Spring 3 开始,支持在XML配置文件中使用 p 命名空间。





注: 设以上内容存在于类路径下的 io/malajava/ioc/injection/injection-setter-p-namespace.xml 文件中。

使用 p 命名空间时需要注意:

Java 语言中 8 种基本数据类型的属性可以直接在等号之后书写 字面值
8 种基本数据类型对应的包装类类型的属性可以直接在等号之后书写 字面值
java.lang.String 类型的属性可以直接在等号之后书写 字面值
所有引用类型(包括包装类类型和String类型)的属性都可以使用 -ref 来引用其它 bean
另外,千万要注意,只有在 标记中增加了以下内容才可以使用p命名空间:

xmlns:p="http://www.springframework.org/schema/p"

Tesging
public class SetterInjectionTest2 {

public static void main(String[] args) {

    DateFormat df = new SimpleDateFormat( "yyyy-MM-dd" );

    // 指定 Configuration Metadata
    String configLocation = "classpath:io/malajava/ioc/injection/injection-setter-p-namespace.xml" ;

    // 创建 Spring IoC 容器
    ApplicationContext iocContainer = new ClassPathXmlApplicationContext( configLocation ) ;

    // 从容器中获取 bean
    Sinaean s = iocContainer.getBean( "huaan" , Sinaean.class );
    System.out.println( s ); // s.toString()
    System.out.println( df.format( s.getBirthdate() ) );

}

}
2、Constructor-based dependency injection
2.1、使用 标签实现参数注入
Java Bean
参见前面步骤中的 Sinaean 类
Configuration Metadata

设以下内容存在于类路径下的 io/malajava/ioc/injection/injection-constructor-arg.xml 文件中。




    
    
    




    
    
    
    
    




    
    
    

对于以下类型的参数来说,可以直接使用

Java 语言中 8 种基本数据类型
8 种基本数据类型对应的包装类类型
java.lang.String 类型
所有引用类型(包括包装类类型和String类型),都可以通过



    




    



    
    
    

所有引用类型(包括包装类类型和String类型),也都可以在



    




    



    
        
            
        
    
    
        
            
        
    
    

实际应用时可以根据实际情况,灵活应用。

Testing
public class ConstructorInjectionTest1 {

public static void main(String[] args) {

    // 指定 Configuration Metadata
    String configLocation = "classpath:io/malajava/ioc/injection/injection-constructor-arg.xml" ;

    // 创建 Spring IoC 容器
    ApplicationContext iocContainer = new ClassPathXmlApplicationContext( configLocation ) ;

    Sinaean s = null ;

    // 从容器中获取 bean
    s = iocContainer.getBean( "first" , Sinaean.class );
    System.out.println( s ); // s.toString()

    s = iocContainer.getBean( "second" , Sinaean.class );
    System.out.println( s ); // s.toString()

    s = iocContainer.getBean( "third" , Sinaean.class );
    System.out.println( s ); // s.toString()

    s = iocContainer.getBean( "fourth" , Sinaean.class );
    System.out.println( s ); // s.toString()

}

}
2.2、使用 c 命名空间 实现参数注入
Java Bean
参见前面步骤中的 Sinaean 类
Configuration Metadata
在 Spring 配置文件中通过添加以下内容来使用 c 命名空间:

   xmlns:c="http://www.springframework.org/schema/c"

添加后的 标签如下所示:


设以下内容存在于类路径下的 io/malajava/ioc/injection/injection-constructor-c.xml 文件中。

Testing public class ConstructorInjectionTest2 {
public static void main(String[] args) {

    // 指定 Configuration Metadata
    String configLocation = "classpath:io/malajava/ioc/injection/injection-constructor-c.xml" ;

    // 创建 Spring IoC 容器
    ApplicationContext iocContainer = new ClassPathXmlApplicationContext( configLocation ) ;

    Sinaean s = null ;

    // 从容器中获取 bean
    s = iocContainer.getBean( "first" , Sinaean.class );
    System.out.println( s ); // s.toString()

    s = iocContainer.getBean( "second" , Sinaean.class );
    System.out.println( s ); // s.toString()

    s = iocContainer.getBean( "third" , Sinaean.class );
    System.out.println( s ); // s.toString()

    s = iocContainer.getBean( "fourth" , Sinaean.class );
    System.out.println( s ); // s.toString()

}

}
© 著作权归作者所有

你可能感兴趣的:(框架)