05 Spring框架 依赖注入(二)

上一节我们讲了三种信息的注入,满足一个类的属性信息的注入,但是如果我们需要向一个实例中注入另一个实例呢?就像我们创建一个学生类,里边有:姓名,性别,年龄,成绩等几个属性(我习惯把类的域叫做属性),但是成绩可以是一个类,可以用这个类创建一个成绩域,即成绩里面有:语文,数学,英语......等几个属性。(上一节我们已经做了一个实验) Spring中信息的注入也是这样,可以注入各种信息,接下来我们来罗列一下这几个注入方法。 各种类型信息的注入:

  • 注入字符串,单个数值。
  • 注入bean对象
  • 注入集合Array,list,set,Map,properties
  • 注入外部信息
  • 注入Spring表达式
  • byName注入和byType注入
  • 抽象bean 前面我们已经说的就是字符串和单个数值的注入和注入bean对象,接下来我们说一下其他的几种注入方式。
<!--set注入 其他bean(上一节已经有例子) -->
<bean id="c4" class="com.Spring.Demo.Student">
<property name="c" ref="c2"></property>
<property name="p" ref="c3"></property>
</bean>

这里的ref指的是其他实例的id 这样就可以将其他实例注入当前的bean中。

注入list,map,set,properties,就像注入字符串和单个数值那样,只是这里注入的是一组集合而已。

<bean id="c5" class="com.Spring.Demo.MessageBean">
<property name="name" value="Tom"></property>
<property name="age" value="18"></property>
<property name="birth" value="2000-10-1"></property>

<!--信息的外部注入 friends在下边会给出 -->
<property name="friends" ref="friends"></property>


<!-- set的信息注入 /和list/Array的方法相同-->
<property name="cities">
<set>
<value>上海</value>
<value>北京</value>
</set>
</property>

<!-- Map的注入方式 -->
<property name="books">
<map>
<entry key="10001" value="java基础"></entry>
<entry key="10002" value="javaWeb开发"></entry>
</map>
</property>
<!-- properties的注入方式 -->
<property name="db">
<props>
   <prop key="dbname">root</prop>
   <prop key="password">123</prop>
</props>
</property>
</bean>

Spring表达式(SPEL)的注入(注入其他bean的值):

<bean id="" class="">  
    <!--map的表达式-->
    <property name="" value="#{id名字.key}"></property> 
    <!--若是属性,对应的实体类应该有getter方法。-->
    <property name="" value="#{id名字.属性}"></property>
    <!--如果引用的是一个list,可以使用方括号进行选取值-->
    <property name="" value="#{id名字.SomeList.[0]}">
    </property> 
    <!--产生0-1的随机数-->
    <property name="" value="#{T(java.lang.Math).random()}"></property> 
    <!--调用方法-->
    <property name="" value="#{id名字.方法名(此方法要有返回值)}"></property> 
    <!--Spring EL 很强大(不太常用),这里就不一一列举了-->
    
</bean>

外部信息注入

可以单独将集合拿出来,如需使用直接调用。

<!--list的表达式:信息的外部注入,经常用到的值放在这里,方便引用-->
<util:list id="friends">
<value>Tom</value>
<value>Jack</value>
</util:list>

我么来测试一下:

这个是实体类:

package com.Spring.Demo;

import java.sql.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

public class MessageBean {
    private String name;
    private String age;
    private Date birth;
    private List<String> friends;
    private Set<String> cities;
    private Map<String,String> books;
    private Properties db;
    
    public void show(){
        System.out.println("name:"+name);
        System.out.println("age:"+age);
        System.out.println("birth:"+birth);
        for(String s:friends){
            System.out.println("list集合:"+s);    
        
        }
        for(String c:cities){
            System.out.println(c);
        }
        System.out.println("Map的使用输出!");
        Set<Entry<String,String>>booksSet=books.entrySet();
        for(Entry<String, String> e:booksSet){
            System.out.println(e.getKey()  +e.getValue());
        }
        System.out.println("properties的使用");
        Set<Object> keys=db.keySet();
        for(Object key:keys){
            System.out.println(key+":"+db.getProperty(key.toString()));
            
        }
    }
        
    public void setDb(Properties db) {
        this.db = db;
    }

    public void setBooks(Map<String, String> books) {
        this.books = books;
    }

    public void setCities(Set<String> cities) {
        this.cities = cities;
    }

    public void setBirth(String birth) {
        Date date=Date.valueOf(birth);
        this.birth = date;
    }

    public void setName(String name) {
        this.name = name;
    }
    public void setAge(String age) {
        this.age = age;
    }
    public void setFriends(List<String> friends) {
        this.friends = friends;
    }
    

}
package com.Spring.Demo;

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

public class TestMessageBean {
    public static void main(String[]args){
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        MessageBean c5=(MessageBean)ac.getBean("c5");
        c5.show();
        
        
    }

}
name:Tom
age:18
birth:2000-10-01
list集合:Tom
list集合:Jack
上海
北京
Map的使用输出!

byName方式的域属性自动注入

在再章节04里面我们说过域属性为引用类型的时候使用ref进行注入,这一节我们通过bean标签内的autowire属性进行byName方式的域属性自动注入,示例如下:

    <bean id = "book" class = "com.di.ByName.Book" autowire="byName"><!--这里使用byName-->
        <property name = "bname" value = "Java技术"></property>
        <property name = "bnumber" value ="201410185732" ></property>
    </bean>
    <!--这里的id要和book里面的属性命名相同-->
    <bean id = "bpub" class="com.di.ByName.publisher">
        <property name="name" value="清华大学出版社"></property>
        <property name="address" value="xxxx"></property>
    </bean>
public class Book {
    private String bname;
    private String bnumber;
    private publisher bpub;
    //省略了setter和toString方法
}
public class publisher {
    String name;
    String address;
    //省略了setter和toString方法
}
//测试类(Junit)
public class test {
    @Test
    public void Test01() {
        String resource = "com/di/ByName/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
        Book book = (Book)ac.getBean("book");
        System.out.println(book);
    }
}
//控制台输出
Book [bname=Java技术, bnumber=201410185732, bpub=publisher [name=清华大学出版社, address=xxxx]]

这样配置过后,程序运行起来,容器就会帮助我们将域属性名作为id到它内部找名称相同的bean进行注入。

byType方式的域属性自动注入:

byType方式的自动注入和byName基本相同,唯一不同点是: 当我们有一个类继承publisher的时候,恰好我们配置文件中也注册了这个bean,这个时候如果autowire属性为byType时,就能够注入这个继承publisher类子类的bean(向上转型)。但是同一个配置文件中不能够同时注册相同类型的bean,否则不唯一,容器不知道我们注入的是哪一个,自然而然也就会报错了。

这种情况下(使用byType),我们可以将它注入的bean的id删除,即匿名bean,因为我们是通过扫描类型来完后注入的,不需要id。

还有一种,可以将匿名bean直接放入需要注入的property中:

这个内部匿名bean就只能由myStudent来使用。

同类抽象bean

就像java里面的抽象类一样,我们注册bean的时候还可以命名抽象bean,用来防止信息的冗余。

    <bean id="baseStudent" 
    <!--abstract="true",使得不能够在程序中通过getBean获取-->
    class="com.di.AbstractBean.Student" abstract="true">
        <property name="school" value="哈佛大学"></property>
        <property name="grade" value="3"></property>
    </bean>
    <!--parent="baseStudent" 继承指定的bean-->
    <bean id="student1" 
    class="com.di.AbstractBean.Student" parent="baseStudent">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
    </bean>
    
    <bean id="student2" class="com.di.AbstractBean.Student" parent="baseStudent"  >
        <property name="id" value="2"></property>
        <property name="name" value="李四"></property>
    </bean>
    
    <bean id="student3" class="com.di.AbstractBean.Student" parent="baseStudent">
        <property name="id" value="3"></property>
        <property name="name" value="王五"></property>
    </bean>

(上面省略了其他代码)这样就减轻了我们配置时候的负担。

异类抽象bean

和我们同类抽象bean相同,继承base bean的bean可以是不同的类注册的bean(但是它们有相同的部分),这样也能够进行继承。

<bean id="base" abstract="true">
    <property name="school" value="哈佛大学"></property>
</bean>


<bean id="student" 
class="com.di.AbstractBean.Student" parent="base">
    <property name="id" value="1"></property>
    <property name="name" value="张三"></property>
</bean>

<bean id="teacher" class="com.di.AbstractBean.Teacher" parent="base"  >
    <property name="id" value="2"></property>
    <property name="name" value="李四"></property>
</bean>

```

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java工会

Spring中的9种设计模式汇总

又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。

1032
来自专栏技术记录

通讯协议序列化解读(一) Protobuf详解教程

前言:说到JSON可能大家很熟悉,是目前应用最广泛的一种序列化格式,它使用起来简单方便,而且拥有超高的可读性。但是在越来越多的应用场景里,JSON冗长的缺点导致...

1091
来自专栏爱撒谎的男孩

Spring表达式和自动装配

4258
来自专栏Jerry的SAP技术分享

Java异常处理:如何写出“正确”但被编译器认为有语法错误的程序

文章的标题看似自相矛盾,然而我在“正确”二字上打了引号。我们来看一个例子,关于Java异常处理(Exception Handling)的一些知识点。

1253
来自专栏程序员互动联盟

【编程基础】C语言常见宏定义

我们在使用C语言编写程序的时候,常常会使用到宏定义以及宏编译指令,有的可能比较常用,有的可能并不是很常用,是不是所有的C语言宏定义以及宏指令你都清楚呢? 指令 ...

3738
来自专栏IT技术精选文摘

跟着实例学习ZooKeeper的用法: 队列

使用Curator也可以简化Ephemeral Node (临时节点)的操作。Curator也提供ZK Recipe的分布式队列实现。 利用ZK的 PERSIS...

2617
来自专栏大内老A

yield在WCF中的错误使用——99%的开发人员都有可能犯的错误[上篇]

在定义API的时候,对于一些返回集合对象的方法,很多人喜欢将返回类型定义成IEnumerable<T>,这本没有什么问题。这里要说的是另一个问题:对于返回类型为...

1808
来自专栏Kirito的技术分享

警惕不规范的变量命名

就在最近,项目组开始强调开发规范了,今天分享一个变量名命名不规范的小案例,强调一下规范的重要性。 Boolean变量名命名规范 16年底,阿里公开了《Java...

3309
来自专栏前端学习心得

异步解决方案----Promise与Await

1665
来自专栏互联网杂技

前端异步代码解决方案实践(二)

早前有针对 Promise 的语法写过博文,不过仅限入门级别,浅尝辄止食而无味。后面一直想写 Promise 实现,碍于理解程度有限,多次下笔未能满意。一拖再拖...

2116

扫码关注云+社区