原标题:day04-Spring管理Bean-IOC-02
BookStore.java:
package com.li.bean;
import java.util.List;
/**
* @author 李
* @version 1.0
*/
public class BookStore {
private List
//如果类中没有其他构造器,默认构造器可以不写
// 如果有其他构造器,则必须显示定义无参构造器
public BookStore() {
}
public List
return bookList;
}
public void setBookList(List
this.bookList = bookList;
}
@Override
public String toString() {
return "BookStore{" +
"bookList=" + bookList +
'}';
}
}
如果有多个BookStore对象,list的内容都一样,按照之前的做法,每一个list都要写上相同的value值。但使用util命名空间可以达到数据复用的效果。
beans.xml:
注意引入util命名空间,一般来说ide会有提示,如果没有则按如下引入:
SpringBeanTest:
package com.li.test;
import com.li.bean.BookStore;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
/**
* @author 李
* @version 1.0
*/
public class SpringBeanTest {
//使用util:list名称空间给属性赋值
@Test
public void setBeanByUtilList() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
BookStore bookStore = ioc.getBean("bookStore", BookStore.class);
System.out.println("bookStore=" + bookStore);
}
}
案例说明:spring的ioc容器,可以直接给对象属性的属性赋值,即级联属性赋值
完成步骤:
(1)创建Dept.java和Emp.java
(2)配置beans.xml
Dept.java:
package com.li.bean;
/**
* @author 李
* @version 1.0
* 部门类
*/
public class Dept {
private String name;
public Dept() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dept{" +
"name='" + name + '\'' +
'}';
}
}
Emp.java:
packag文章来源地址58107.htmle com.li.bean;
/**
* @author 李
* @version 1.0
* 员工类
*/
public class Emp {
private String name;
private Dept dept;
public Emp() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"name='" + name + '\'' +
", dept=" + dept +
'}';
}
}
beans.xml:
SpringBeanTest:
package com.li.test;
import com.li.bean.Emp;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
/**
* @author 李
* @version 1.0
*/
public class SpringBeanTest {
//使用级联赋值给属性的属性赋值
@Test
public void setBeanByRelation() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Emp emp = ioc.getBean("emp", Emp.class);
System.out.println("emp=" + emp);
}
}
在spring的ioc容器,可以通过静态工厂获取bean对象
完成步骤:
(1)静态工厂类MyStaticFactory类和Monster类
(2)配置beans.xml
Monster类详见上一篇--2.1通过类型来获取bean
MyStaticFactory.java:
package com.li.factory;
import com.li.bean.Monster;
import java.util.HashMap;
import java.util.Map;
/**
* @author 李
* @version 1.0
* 静态工厂类-可以返回Monster对象
*/
public class MyStaticFactory {
private static Map
//使用static静态代码块进行初始化
// (静态代码块在类加载的同时就直接执行,且只执行一次)
static {
mOnsterMap= new HashMap<>();
monsterMap.put("monster01", new Monster(100, "孙悟空", "七十二变"));
monsterMap.put("monster02", new Monster(200, "金蝉子", "普渡众生"));
}
//提供一个方法,返回monster对象
public static Monster getMonster(String key) {
return monsterMap.get(key);
}
}
beans.xml:
SpringBeanTest:
package com.li.test;
import com.li.bean.Monster;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
/**
* @author 李
* @version 1.0
*/
public class SpringBeanTest {
//使用静态工厂来获取 bean
@Test
public void getBeanByStaticFactory() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster my_monster01 = ioc.getBean("my_monster01", Monster.class);
//这里如果使用的是相同id获取bean,那么获取的实际上是同一个对象,例如:
Monster my_monster001 = ioc.getBean("my_monster01", Monster.cwww.yii666.comlass);
// 因为静态工厂中的静态代码块只执行一次,这里不同的对象引用指向的都是同一个对象
System.out.println(my_monster01 == my_monster001);//true
System.out.println("my_monster01=" + my_monster01);
}
}
Monster类详见上一篇--2.1通过类型来获取bean
MyInstanceFactory:
package com.li.factory;
import com.li.bean.Monster;
import java.util.HashMap;
import java.util.Map;
/**
* @author 李
* @version 1.0
* 实例工厂类
*/
public class MyInstanceFactory {
private Map
//通过普通代码块进行初始化
//普通代码块每创建一个对象就会执行一次
{
monster_map = new HashMap<>();
monster_map.put("monster03", new Monster(300, "猪八戒", "九尺钉耙"));
monster_map.put("monster04", new Monster(400, "沙和尚", "丈二禅杖"));
}
//写一个方法返回Monster对象
public Monster getMonster(String key) {
return monster_map.get(key);
}
}
beans.xml:
SpringBeanTest:
package com.li.test;
import com.li.bean.Monster;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
/**
* @author 李
* @version 1.0
*/
public class SpringBeanTest {
//使用实例工厂来获取 bean
@Test
public void getBeanByInstanceFactory() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster my_monster02 = ioc.getBean("my_monster02", Monster.class);
System.out.println("my_monster02=" + my_monster02);
// 这里使用相同的id获取bean,那么返回的对象也是同一个!!
Monster my_monster002 = ioc.getBean("my_monster02", Monster.class);
// 因为虽然是实例工厂,但是两次 ioc.getBean("my_monster02", Monster.class)使用的都是
// 同一个工厂实例(id="myInstanceFactory"),返回的自然也就是同一个实例工厂中的 monster
System.out.println(my_monster02 == my_monster002);//true
//换而言之,如果不是同一个实例工厂,那么返回的就不是同一个对象了
//(这里的my_monster03,在beans.xml使用的是 id=myInstanceFactory02的实例工厂)
Monster my_monster03 = ioc.getBean("my_monster03", Monster.class);
System.out.println("my_monster03=" + my_monster03);
System.out.println(my_monster02 == my_monster03);//false
}
}
在spring的ioc容器,通过FactoryBean获取bean对象
MyFactoryBean:
package com.li.factory;
import com.li.bean.Monster;
import org.springframework.beans.factory.FactoryBean;
import java.util.HashMap;
import java.util.Map;
/**
* @author 李
* @version 1.0
* FactoryBean
*/
public class MyFactoryBean implements FactoryBean
//这个就是你配置的时候,指定要获取的对象对应的key
private String key;
private Map
//代码块完成初始化
{
monster_map = new HashMap<>();
monster_map.put("monster05", new Monster(5, "黑风怪", "翻江倒海"));
monster_map.put("monster06", new Monster(6, "金角大王", "超能力"));
}
public void setKey(String key) {
this.key = key;
}
@Override
public Monster getObject() throws Exception {
return monster_map.get(key);
}
@Override
public Class> getObjectType() {
return Monster.class;
}
@Override
public boolean isSingleton() {//这里指定是否是单例对象
return true;
}
}
beans.xml:
SpringBeanTest:
package com.li.test;
import com.li.bean.Monster;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
/**
* @author 李
* @version 1.0
*/
public class SpringBeanTest {
//通过FactoryBean获取bean对象
@Test
public void getBeanByFactoryBean() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster my_monster05 = ioc.getBean("my_monster05", Monster.class);
System.out.println("my_monster05=" + my_monster05);
}
}
在spring的ioc容器中,提供了一种继承的方式来实现bean配置信息的重用
beans.xml:
SpringBeanTest:
package com.li.test;
import com.li.bean.Monster;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.testng.annotations.Test;
/**
* @author 李
* @version 1.0
*/
public class SpringBeanTest {
//配置Bean(通过继承)
@Test
public void getBeanByFactoryBean() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster monster10 = ioc.getBean("monster10", Monster.class);
Monster monster11 = ioc.getBean("monster11", Monster.class);
System.out.println("monster10=" + monster10);
System.out.println("monster11=" + monster11);
}
}
注意:
如果bean指定了abstract="true" 表示该bean对象是只用于被继承的
那么这个bean就不能被获取/实例化
此时如果输出monster10,就会显示错误:
在spring的ioc容器,默认是按照配置的顺序创建bean对象。比如:
会先创建 student01 这个 bean 对象,然后创建 department01 这个 bean 对象
但如果这样配置:
会先创建 department01 对象,再创建 student01 对象.
例子
Student:
package com.li.bean;
/**
* @author 李
* @version 1.0
*/
public class Student {
public Student() {
System.out.println("Student 构造器被执行...");
}
}
Department:
package com.li.bean;
/**
* @author 李
* @version 1.0
*/
public class Department {
public Department() {
System.out.println("Department 构造器被执行...");
}
}
beans.xml:
测试类:
//测试 Bean的创建顺序
@Test
public void testBeanByCreate() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("ok~");
}
如果我们在配置student01对象时,加上depends-on="department01"
,spring就会认为你的student01对象时依赖于department01对象,会先创建department01对象。
总结:在默认情况下,bean创建的顺序是按照默认配置顺序来的。但是如果我们在对象配置中指定了依赖对象,就会先创建被依赖的对象。
1.先看下面的配置,请问两个bean创建的顺序是什么?并分析执行流程
(1)先创建 id=memberDaoImpl 的对象
(2)再创建 id=memberServiceImpl 的对象
(3)调用 memberServiceImpl.setMemberDAO() 方法,完成引用
2.先看下面的配置,请问两个bean创建的顺序是什么?并分析执行流程
(1)先创建 id=memberServiceImpl 的对象
(2)再创建 id=memberDaoImpl 的对象
(3)调用 memberServiceImpl.setMemberDAO() 方法,完成引用
总结:ioc容器会把整个bean的创建当做一个整体来对待,会把配置文件中所有对象bean先创建好,然后才完成对象间的引用。
见2.4
在spring的ioc容器中,默认是按照单例创建的,即配置一个bean对象后,ioc容器只会创建一个bean实例。
如果希望ioc容器配置的某个bean对象,是以多个实例形式创建的,可以通过配置scope="prototype"来指定。
例子1-单例对象
Cat:
package com.li.bean;
/**
* @author 李
* @version 1.0
*/
public class Cat {
private Integer id;
private String name;
public Cat() {
System.out.println("Cat() 构造器被执行...");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
beans.xml:
测试类:
//测试Scope
@Test
public void testBeanScope() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Cat cat1 = ioc.getBean("cat", Cat.class);
Cat cat2 = ioc.getBean("cat", Cat.class);
Cat cat3 = ioc.getBean("cat", Cat.class);
System.out.println("cat1="+cat1);
System.out.println("cat2="+cat2);
System.out.println("cat3="+cat3);
}
输出如下:地址值相同,证明这三个对象引用都指向了同一个对象
例子2-多例对象
现在我们把例子1的cat对象的配置改为scope="prototype"
输出如下:构造器执行了三次,说明创建了三个Cat对象(对象的地址值也不一样)
当bean为scope="singleton"(默认值),在启动容器时,就会创建单例对象,并放入singletonObjects集合
当bean设置为scope="prototype",即设置为多实例机制后,该bean是在getBean时才创建
如果是单例singleton,但又希望在getBean时才创建,可以指定懒加载lazy-init="true" (默认值是false)
通常情况下,lazy-init 使用默认值false,因为在开发看来,用空间换时间是值得的,除非有特殊要求。
如果scope="prototype",这时你的lazy-init属性值不管设置为什么,都默认为true
因为多例情况下,spring无法知道创建几个对象,因此只有在用到的时候才能创建
来源于:day04-Spring管理Bean-IOC-02