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基本相同,唯一不同点是:
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>
版权声明:本文为博主原创文章,如需转载请表明出处。 https://blog.csdn.net/qq_39266910/article/details/77828699