话说:
各位读者朋友,晚上好!看了前面几篇博客,也许有读者嘲笑,什么年代了,还在总结Hibernate、Struts2这些“陈旧”滴框架……
笔者总是相信,明历史,才能更好的看未来。不站在巨人的肩膀上,框架能发展到现在滴模样么。而且,从最原始的理解,一些设计思想非常经典,技术都是其次,思想最重要。
今天总结一下Sping。正如它滴名字,寓意着生机盎然,绿色环保,基业长青。也许用词不当,但是总能表达这是一个非常经典,至今仍旧魅力无限的框架!它的官网也是一片蓬勃之绿,简洁明快,干练大气。
目录:
一、整体架构
二、Spring概念及环境搭建
三、ApplicationContext与BeanFactory的区别
四、单例与”多例“在bean中的体现
五、如何用Java代码实现一个单例?
六、属性注入
七、总结
开发环境:
IntelliJ IDEA(2017.2.5)
Mavan web项目
一、整体架构
二、Spring概念及环境搭建
概念
IoC-Inversion of Control 控制反转
这是Spring世界中的关键字之一。简单说就是把我们之前每次new对象的控制权全权授予spring.xml配置文件中的bean去处理,我们只负责调用即可。
还有几个关键词,后续遇到再细说:DI——Dependency Injection 依赖注入 、AOP——Aspect-Oriented Programming面向切面编程
https://docs.spring.io/spring/docs/5.0.1.RELEASE/spring-framework-reference/core.html#beans
环境搭建
1)下载源码包
http://repo.spring.io/release/org/springframework/spring/
下载这个有啥用呢?里面有个docs文件夹,各种帮助文档,应有尽有!离线的,方便查看;还可以参考各种配置等;
2)导入.jar包
通过maven的pom.xml导入依赖,暂时可以只导入core,后续根据需要全部导入。
3)配置spring.xml
配置文件默认名:applicationContext.xml
我们修改为:spring.xml
随便修改,就是加载的时候,写清楚名字即可。核心是配置头部声明和bean。
4)如何获取bean?
a、定义JavaBean。这里Hello
<!--创建Hello Bean-->
<!--name自定义-->
<bean name="hello" class="com.hmc.spring.Hello" ></bean>
b、加载spring.xml配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
c、获取指定的bean
//2 获取指定的bean
Hello hello =(Hello) ac.getBean("hello");
d、调用bean中的方法
//3 调用相应的属性和方法
hello.say();
三、ApplicationContext与BeanFactory的区别
具体区别详见代码,代码中注解很详细
SpringTest
package com.hmc.spring;
import com.hmc.spring.action.BookAction;
import com.hmc.spring.dao.BookDao;
import com.hmc.spring.model.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* User:Meice
* 2017/11/3
*/
public class SpringTest {
//调用bean法一:
@Test
public void test01() {
//1 加载spring.xml配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//2 获取指定的bean
Hello hello =(Hello) ac.getBean("hello");
//3 调用相应的属性和方法
hello.say();
/**
* 运行结果:
* 十一月 03, 2017 3:49:40 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* Hello Spring!
*/
/**
* 总结:
* 1、ApplicationContext是个接口,ClassPathXmlApplicationContext实现了这个接口;
* 2、这里我们并没有new Hello这个类,但是却调用了里面的方法,原因就在于bean的作用。spring.xml中配置bean的时候,容器已经
* 帮我们实例化了;
* 3、这里就是典型的IoC-Inversion of Control 把new 对象的权利交给配置文件,而不是我们自己每次new;所以,以后的类如何实例化呢?
* 就是在spring.mxl中配置即可.
* 4、这里的目的不是说出这句话,是体会IoC这种思想。
*/
}
//调用bean法二:
@Test
public void test02() {
BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml");
Hello hello =(Hello) factory.getBean("hello");
hello.say();
}
/**
* 运行结果:
* 十一月 03, 2017 4:14:03 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* Hello Spring!
*/
/**
* 以上两种方式区别:
* 1、ApplicationContext在应用服务器开启的时候,就把所有bean实例化;整体来看效率高,单次来看效率低;
* 2、BeanFactory在getBean()的时候在实例化,单次效率高,整体效率低。
* 3、类似的原理还有:Hibernate中获取单个对象的get()和load()方法;数据连接池;lazy修饰符(Scala)
*
*/
@Test
public void test03() {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//得到bean的时候指定bean类型,避免类型转换
Hello hello = ac.getBean("hello",Hello.class);
hello.say();
}
}
完整版的spring.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置文件名默认applicationContext.xml 这里我们修改为spring.xml-->
<!--创建Hello Bean-->
<!--name自定义-->
<bean name="hello" class="com.hmc.spring.Hello" ></bean>
<!--为了测试单例,这里利用之前的BookAction做演练-->
<bean name="book" class="com.hmc.spring.model.Book" scope="singleton">
<!--单属性注入-->
<property name="name" value="《儒林外史》"></property>
<!--多属性-数组注入-->
<property name="names" value="《茶花女》,《瓦尔登湖》,《追风筝的人》,《红与黑》"></property>
<property name="names2">
<array>
<value>《子夜》</value>
<value>《茶馆》</value>
<value>《丰乳肥臀》</value>
</array>
</property>
<!--多属性List<>集合注入-->
<property name="nameList" value="《格林童话》"></property>
<property name="nameList2">
<list>
<value>《阿里巴巴与四十大盗》</value>
<value>《安徒生童话》</value>
<value>《伊索寓言》</value>
</list>
</property>
<!--List<对象>属性注入-->
<property name="bookList" ref="bk1">
</property>
<!--List<对象>多属性注入-->
<property name="bookList2">
<list>
<ref bean="bk1"></ref>
<ref bean="bk2"/>
<ref bean="bk3"/>
</list>
</property>
<!--Map属性注入-->
<property name="nameMap">
<map>
<entry key="1" value-ref="bk1"></entry>
<entry key="2" value-ref="bk3"></entry>
</map>
</property>
<!--Set属性注入-->
<property name="bookSet">
<set>
<ref bean="bk1"></ref>
<ref bean="bk2"/>
<ref bean="bk3"/>
</set>
</property>
</bean>
<bean name="bk1" class="com.hmc.spring.model.Book">
<property name="name" value="《碧血剑》"></property>
</bean>
<bean name="bk2" class="com.hmc.spring.model.Book">
<property name="name" value="《书剑恩仇录》"></property>
</bean>
<bean name="bk3" class="com.hmc.spring.model.Book">
<property name="name" value="《连城诀》"></property>
</bean>
<bean name="bookDao" class="com.hmc.spring.dao.BookDao"></bean>
<bean name="bookAction" class="com.hmc.spring.action.BookAction"></bean>
</beans>
四、单例与”多例“在bean中的体现
Spring里面通过scope属性来控制单例模式的。scope="singleton"表示单例(不论如何new,都是一个对象);scope = "prototype"表示多例。调用一次bean,就是一个全新的实例。
测试类SpringTest
package com.hmc.spring;
import com.hmc.spring.action.BookAction;
import com.hmc.spring.dao.BookDao;
import com.hmc.spring.model.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* User:Meice
* 2017/11/3
*/
public class SpringTest {
@Test
public void test04(){
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
Hello hello1 = ac.getBean("hello",Hello.class);
Hello hello2 = ac.getBean("hello",Hello.class);
System.out.println(hello1==hello2);
System.out.println(hello1.equals(hello2));
/**
* 运行结果:
* 十一月 03, 2017 5:56:32 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* true
*/
/**
* 一个对象,我们两次getBean,按照之前思想,相当于new了两次,这两个对象自然不同
* 但是呢,这里确实true?
* 这就是singleton。 最直白的体现
* scope属性控制单例和多例模式;默认是单例模式scope="singleton";多例是scope="prototype"
*/
}
@Test
public void testBookAction(){
//可以把获取ac定义为static{},避免每次获取,麻烦
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
BookDao bd = ac.getBean("bookDao",BookDao.class);
Book bk1 = ac.getBean("book",Book.class);
Book bk2 = ac.getBean("book",Book.class);
// bk1.setName("三国演义");
// bk2.setName("西游记");
bd.add(bk1);
bd.add(bk2);
/**
* 运行结果:
* 十一月 03, 2017 6:14:26 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* 增加了《西游记》
* 增加了《西游记》
* 以上我明明获取了2个book对象(bean);并且赋值不一样,结果呢?后者覆盖了前者
* 此时,配置文件保持默认,下来一个测试,修改配置文件scope属性为 prototype类型
*
*
* 运行结果:
* 十一月 03, 2017 6:19:07 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* 增加了《三国演义》
* 增加了《西游记》
* 这是框架通过scope属性方式来控制单例和多例;我们自己也可以写的。
*/
/**
* 有什么卵用呢?
* 作用大了呢!存在即是合理的。
* 比如Book这个bean,我们增加、修改等操作,都是不同的对象,就是和用多例;而BookAction基本不变,
* 就用单例。
* 生活中也有很多单例案例:比如你听歌曲,每次只能听一首歌,程序是不会允许你同时听两首歌曲的...
* 还有很多类似案例,灰常有趣,读者可以自行查找相关资料奥!
*/
}
}
笔者在这里结合了上一篇博客图书管理系统中的例子,来演示了下单例、多例。
调动时候,要厘清关系。
以上仅仅为演示,所以真实情况并没有配置Struts2,其中:
BookAction
package com.hmc.spring.action;
import com.hmc.spring.dao.BookDao;
import com.hmc.spring.model.Book;
/**
* User:Meice
* 2017/11/3
*/
public class BookAction {
BookDao bd = new BookDao();
private Book book;
public String add() {
bd.add(book);
return "success";
}
}
BookDao
package com.hmc.spring.dao;
import com.hmc.spring.model.Book;
/**
* User:Meice
* 2017/11/3
*/
public class BookDao {
//定义一个方法增加图书
public void add(Book book) {
System.out.println("增加了《"+book.getName()+"》");
}
}
Book
package com.hmc.spring.model;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* User:Meice
* 2017/11/3
*/
public class Book {
private String name;//单属性注入
private String names[];//多属性数组注入-法一
private String names2[];//多属性数组注入-法二
private List<String> nameList;//List属性注入-法一
private List<String> nameList2;//多属性List注入-法二
private List<Book> bookList;//List<对象>属性注入
private List<Book> bookList2;//List<对象>多属性注入
private Map<Integer,Book> nameMap;//Map属性注入
private Set<Book> bookSet;//Set属性注入
/**
* 属性注入本质是依赖set()方法的,所以
* 属性都要生成或者自己写get() set()方法,注意name值等于setYy中的yy
*/
public Set<Book> getBookSet() {
return bookSet;
}
public void setBookSet(Set<Book> bookSet) {
this.bookSet = bookSet;
}
public Map<Integer, Book> getNameMap() {
return nameMap;
}
public void setNameMap(Map<Integer, Book> nameMap) {
this.nameMap = nameMap;
}
public List<Book> getBookList2() {
return bookList2;
}
public void setBookList2(List<Book> bookList2) {
this.bookList2 = bookList2;
}
public List<Book> getBookList() {
return bookList;
}
public void setBookList(List<Book> bookList) {
this.bookList = bookList;
}
public List<String> getNameList2() {
return nameList2;
}
public void setNameList2(List<String> nameList2) {
this.nameList2 = nameList2;
}
public List<String> getNameList() {
return nameList;
}
public void setNameList(List<String> nameList) {
this.nameList = nameList;
}
public String[] getNames2() {
return names2;
}
public void setNames2(String[] names2) {
this.names2 = names2;
}
public String[] getNames() {
return names;
}
public void setNames(String[] names) {
this.names = names;
}
public Book() {}
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
/* public void setName(String name) {
this.name = name;
}*/
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
'}';
}
}
这里面之所以有这么多属性,是为第六个属性注入用的。
五、如何用Java代码实现一个单例?
单例设计模式就是一个实例。有什么用呢?应用非常广泛!比如播放音乐,每次只能播放一首歌,这就是典型的单例模式。
还有其他很多有趣应用,读者感兴趣,可以参考:
http://blog.youkuaiyun.com/tanyujing/article/details/14160941
这里我们自己来实现一个单例。
PlayMusic
package com.hmc.spring.singleton;
/**
* User:Meice
* 2017/11/3
*/
public class PlayMusic {
//这一步是单例模式的核心-把构造方法私有化,外边就无法无休止的实例化
private PlayMusic(){}
private static PlayMusic pm;
public static PlayMusic getInstance() {
if(pm == null) {
pm = new PlayMusic();
}
return pm;
}
public void play(String music) {
System.out.println("演奏了音乐:"+music);
}
/**
* 以前我们是这么处理年龄的
*/
/* private int age;
public void setAge(int age) {
if (age>100){
age = 80;
}
}*/
}
TestMusic
package com.hmc.spring.singleton;
/**
* User:Meice
* 2017/11/3
*/
public class TestMusic {
public static void main(String[] args) {
// PlayMusic pm = new PlayMusic();
// PlayMusic pm2 = new PlayMusic();
PlayMusic pm = PlayMusic.getInstance();
PlayMusic pm2 = PlayMusic.getInstance();
System.out.println(pm == pm2);
System.out.println("我是第一次实例化后的PlayMusic对象:"+pm);
System.out.println("我是第二次实例化后的PlayMusic对象:"+pm2);
pm.play("黑色的夜");
pm.play("吻别");
/**
* 运行结果:
* true
* 我是第一次实例化后的PlayMusic对象:com.hmc.spring.singleton.PlayMusic@610455d6
* 我是第二次实例化后的PlayMusic对象:com.hmc.spring.singleton.PlayMusic@610455d6
* 演奏了音乐:黑色的夜
* 演奏了音乐:吻别
*/
}
}
以上可知,设计一个单例模式的关键是:
1、构造方法私有化,避免多次new;
2、给外界一个方法来实例化,类似ModelDriven的方式来进行判断,使其只能new一次。一旦new一次之后,再次new的时候,就直接返回已经new的对象。
六、属性注入
属性注入,顾名思义,就是为属性赋值。之前我们都是实例化对象后,通过set()方法来赋值的。这里全部转入到配置文件中初始化。复杂一点的是,属性可能是数组或集合。比如实体类之间有外键关联的时候,Employee和Department ;这个时候设置值就稍微复杂点。
Book
就不在赘述,和上面一样。
这里是完整版SpringTest
package com.hmc.spring;
import com.hmc.spring.action.BookAction;
import com.hmc.spring.dao.BookDao;
import com.hmc.spring.model.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* User:Meice
* 2017/11/3
*/
public class SpringTest {
//调用bean法一:
@Test
public void test01() {
//1 加载spring.xml配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//2 获取指定的bean
Hello hello =(Hello) ac.getBean("hello");
//3 调用相应的属性和方法
hello.say();
/**
* 运行结果:
* 十一月 03, 2017 3:49:40 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* Hello Spring!
*/
/**
* 总结:
* 1、ApplicationContext是个接口,ClassPathXmlApplicationContext实现了这个接口;
* 2、这里我们并没有new Hello这个类,但是却调用了里面的方法,原因就在于bean的作用。spring.xml中配置bean的时候,容器已经
* 帮我们实例化了;
* 3、这里就是典型的IoC-Inversion of Control 把new 对象的权利交给配置文件,而不是我们自己每次new;所以,以后的类如何实例化呢?
* 就是在spring.mxl中配置即可.
* 4、这里的目的不是说出这句话,是体会IoC这种思想。
*/
}
//调用bean法二:
@Test
public void test02() {
BeanFactory factory = new ClassPathXmlApplicationContext("spring.xml");
Hello hello =(Hello) factory.getBean("hello");
hello.say();
}
/**
* 运行结果:
* 十一月 03, 2017 4:14:03 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* Hello Spring!
*/
/**
* 以上两种方式区别:
* 1、ApplicationContext在应用服务器开启的时候,就把所有bean实例化;整体来看效率高,单次来看效率低;
* 2、BeanFactory在getBean()的时候在实例化,单次效率高,整体效率低。
* 3、类似的原理还有:Hibernate中获取单个对象的get()和load()方法;数据连接池;lazy修饰符(Scala)
*
*/
@Test
public void test03() {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//得到bean的时候指定bean类型,避免类型转换
Hello hello = ac.getBean("hello",Hello.class);
hello.say();
}
@Test
public void test04(){
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
Hello hello1 = ac.getBean("hello",Hello.class);
Hello hello2 = ac.getBean("hello",Hello.class);
System.out.println(hello1==hello2);
System.out.println(hello1.equals(hello2));
/**
* 运行结果:
* 十一月 03, 2017 5:56:32 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* true
*/
/**
* 一个对象,我们两次getBean,按照之前思想,相当于new了两次,这两个对象自然不同
* 但是呢,这里确实true?
* 这就是singleton。 最直白的体现
* scope属性控制单例和多例模式;默认是单例模式scope="singleton";多例是scope="prototype"
*/
}
@Test
public void testBookAction(){
//可以把获取ac定义为static{},避免每次获取,麻烦
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
BookDao bd = ac.getBean("bookDao",BookDao.class);
Book bk1 = ac.getBean("book",Book.class);
Book bk2 = ac.getBean("book",Book.class);
// bk1.setName("三国演义");
// bk2.setName("西游记");
bd.add(bk1);
bd.add(bk2);
/**
* 运行结果:
* 十一月 03, 2017 6:14:26 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* 增加了《西游记》
* 增加了《西游记》
* 以上我明明获取了2个book对象(bean);并且赋值不一样,结果呢?后者覆盖了前者
* 此时,配置文件保持默认,下来一个测试,修改配置文件scope属性为 prototype类型
*
*
* 运行结果:
* 十一月 03, 2017 6:19:07 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* 增加了《三国演义》
* 增加了《西游记》
* 这是框架通过scope属性方式来控制单例和多例;我们自己也可以写的。
*/
/**
* 有什么卵用呢?
* 作用大了呢!存在即是合理的。
* 比如Book这个bean,我们增加、修改等操作,都是不同的对象,就是和用多例;而BookAction基本不变,
* 就用单例。
* 生活中也有很多单例案例:比如你听歌曲,每次只能听一首歌,程序是不会允许你同时听两首歌曲的...
* 还有很多类似案例,灰常有趣,读者可以自行查找相关资料奥!
*/
}
private static ApplicationContext ac;
static {
ac = new ClassPathXmlApplicationContext("spring.xml");
}
//测试属性初始化:-单个属性注入
@Test
public void test05(){
Book book = ac.getBean("book",Book.class);
System.out.println(book);
/**
* <bean name="book" class="com.hmc.spring.model.Book" scope="singleton">
* <property name="name" value="《儒林外史》"></property>
* </bean>
*
*
*
* 运行结果:
* 十一月 03, 2017 9:11:50 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* Book{name='《儒林外史》
*/
}
/**
* 需要注意:单个属性注入,本质是根据set()方法注入的,name要等于setYy的Yy小写后得yy;
* 去掉set()方法,就会报错:ExceptionInInitializerError
* Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'book' defined
* in class path resource [spring.xml]: Error setting property values; nested exception is org.springframework.
* beans.NotWritablePropertyException: Invalid property 'name' of bean class [com.hmc.spring.model.Book]:
* Bean property 'name' is not writable or has an invalid setter method. Does the parameter type of the
* setter match the return type of the getter?
* 同理,如果属性名不符合setYy的规则,也是找不到的。如果你自己写set方法,就需要特别注意
* 比如:setBookName的属性,配置的时候name="bookName",这样才能找到,而不是name
*/
//测试多个属性注入-数组
@Test
public void test06(){
Book book = ac.getBean("book",Book.class);
System.out.println(book.getNames()[0]);
System.out.println(book.getNames().length);
/**
* 运行结果:
* 十一月 03, 2017 11:19:31 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* 《茶花女》
*/
System.out.println("---------------------------------------");
for(String name : book.getNames()) {
System.out.println(name);
}
/**
* 十一月 03, 2017 11:22:29 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring.xml]
《茶花女》
4
---------------------------------------
《茶花女》
《瓦尔登湖》
《追风筝的人》
《红与黑》
*/
System.out.println("---------------------------------------");
for (String name:book.getNames2()){
System.out.println(name);
}
/**
---------------------------------------
《子夜》
《茶馆》
《丰乳肥臀》
*/
/**
* 规范的写法是用<array></array>
*/
}
//测试List属性注入
@Test
public void testList() {
Book book = ac.getBean("book",Book.class);
System.out.println(book.getNameList());
/**
* 运行结果:
* 十一月 03, 2017 11:35:19 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
* 信息: Loading XML bean definitions from class path resource [spring.xml]
* [《格林童话》]
*/
System.out.println("---------------------------------------");
System.out.println(book.getNameList2());
/**
* 运行结果:
* 十一月 04, 2017 12:06:32 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring.xml]
[《格林童话》]
---------------------------------------
[《阿里巴巴与四十大盗》, 《安徒生童话》, 《伊索寓言》]
*/
System.out.println("---------------------------------------");
for(String name:book.getNameList2()){
System.out.println(name);
}
/**
* 运行结果:
* ---------------------------------------
《阿里巴巴与四十大盗》
《安徒生童话》
《伊索寓言》
*/
System.out.println("---------------------------------------");
//测试List<对象>属性注入
System.out.println(book.getBookList());
/**
* 运行结果:
* ---------------------------------------
[Book{name='《碧血剑》'}]
*/
System.out.println("---------------------------------------");
//测试List<对象>多属性注入
System.out.println(book.getBookList2());
/**
* 运行结果:
* ---------------------------------------
[Book{name='《碧血剑》'}, Book{name='《书剑恩仇录》'}, Book{name='《连城诀》'}]
*/
}
//测试Map属性注入
@Test
public void testMap() {
Book book = ac.getBean("book",Book.class);
System.out.println(book.getNameMap());
/**
* 运行结果:
* 十一月 04, 2017 12:38:39 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring.xml]
{1=Book{name='《碧血剑》'}, 2=Book{name='《连城诀》'}}
*/
System.out.println("---------------------------------------");
//遍历一下
Map<Integer,Book> mapBooks = book.getNameMap();
Set<Integer> keys = mapBooks.keySet();
Iterator<Integer> its = keys.iterator();
while(its.hasNext()) {
Integer key = its.next();
Book bk = mapBooks.get(key);
System.out.println(bk.getName());
}
/**
* 运行结果:
* 十一月 04, 2017 12:54:26 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring.xml]
{1=Book{name='《碧血剑》'}, 2=Book{name='《连城诀》'}}
---------------------------------------
《碧血剑》
《连城诀》
*/
System.out.println("---------------------------------------");
//遍历法二:
Set<Map.Entry<Integer,Book>> setEntry = mapBooks.entrySet();
Iterator<Map.Entry<Integer,Book>> itn = setEntry.iterator();
while (itn.hasNext()) {
Map.Entry<Integer,Book> enty = itn.next();
System.out.println(enty.getValue().getName());
}
}
//测试Set属性注入
@Test
public void testSet() {
Book book = ac.getBean("book",Book.class);
System.out.println(book.getBookSet());
/**
* 运行结果:
* 十一月 04, 2017 1:09:53 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring.xml]
[Book{name='《碧血剑》'}, Book{name='《书剑恩仇录》'}, Book{name='《连城诀》'}]
*/
System.out.println("---------------------------------------");
//遍历取值
Set<Book> books = book.getBookSet();
for(Book bk :books) {
System.out.println(bk.getName());
}
/**
* 运行结果:
* 十一月 04, 2017 1:15:44 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring.xml]
[Book{name='《碧血剑》'}, Book{name='《书剑恩仇录》'}, Book{name='《连城诀》'}]
---------------------------------------
《碧血剑》
《书剑恩仇录》
《连城诀》
*/
}
}
七、总结
1、有了IoC-控制反转,很少在用new了;
2、单例设计模式在Spring中的体现方式是bean的scope属性,分为singleton和prototype; 实际运用中我们可以自己写单例,来匹配业务需求;
3、属性注入为多类型的属性赋值提供了很好的配置方式。
好了,晚安!下期再会!