💖使用utillist进行配置
spring的ioc容器, 可以通过util
名称空间来创建list
集合
1.新建com.zzw.spring.bean.BookStore
public class BookStore {
//书
private List<String> bookList;
//无参构造器, 如果没有其它的构造器, 该无参构造器可以不写
//如果有其它的构造器, 则必须显示地定义一下无参构造器
public BookStore() {
}
//getter, setter方法
}
2.src/beans.xml
增加如下配置
<!--定义一个util:list, 并且指定了id 可以达到数据复用
说明: 在使用util:list 名称空间的时候, 需要引入相应的标签, 一般来说通过alt+enter会自动加入
, 如果没有就手动添加一下
-->
<util:list id="myBookList">
<value>三体</value>
<value>时间简史</value>
<value>梦的解析</value>
<value>福尔摩斯探案集</value>
</util:list>
<!--配置BookStore对象-->
<bean class="com.zzw.spring.bean.BookStore" id="bookStore">
<property name="bookList" ref="myBookList"/>
</bean>
3.测试: com/zzw/spring/test/SpringBeanTest.java
新增setBeanByUtilList
方法
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.新增com.zzw.spring.bean.Dept
部门类
public class Dept {
private String name;
public Dept() {
}
//getter, setter方法
2.新建com.zzw.spring.bean.Employee
员工类
public class Employee {
private String name;
private Dept dept;
public Employee() {
}
//getter, setter方法
}
3.src/beans.xml
增加如下配置
<!--配置Dept对象-->
<bean class="com.zzw.spring.bean.Dept" id="dept"/>
<!--配置Employee对象-->
<bean class="com.zzw.spring.bean.Employee" id="employee">
<property name="name" value="tom"/>
<property name="dept" ref="dept"/>
<!--这里我希望给dept的name属性指定值[级联属性赋值]-->
<property name="dept.name" value="java开发"/>
</bean>
4.测试: com/zzw/spring/test/SpringBeanTest.java
新增setBeanByRelation
方法
public class SpringBeanTest {
//给属性进行级联赋值
@Test
public void setBeanByRelation() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Employee employee = ioc.getBean("employee", Employee.class);
System.out.println("employee=" + employee);
}
}
💖通过静态工厂获取bean
在spring的ioc容器, 可以通过静态工厂获取bean对象
1.新建com.zzw.spring.factory.MyStaticFactory
这是一个静态工厂类-可以返回Monster对象
package com.zzw.spring.factory;
public class MyStaticFactory {
private static Map<String, Monster> monsterMap;
//使用static代码块进行初始化 - java基础
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);
}
}
2.src/beans.xml
增加如下配置
<!--配置Monster对象, 通过静态工厂获取
解读
1.通过静态工厂获取bean
2.class 是静态工厂类的全路径
3.factory-method 表示是指定静态工厂类的哪个方法返回对象
4.constructor-arg value="monster02" value是指定要返回静态工厂的哪一个对象
-->
<bean class="com.zzw.spring.factory.MyStaticFactory" id="myMonster01"
factory-method="getMonster">
<constructor-arg value="monster02"/>
</bean>
3.测试: com/zzw/spring/test/SpringBeanTest.java
新增getBeanByStaticFactory
方法
public class SpringBeanTest {
//通过静态工厂获取bean
@Test
public void getBeanByStaticFactory() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster myMonster01 = ioc.getBean("myMonster01", Monster.class);
Monster myMonster02 = ioc.getBean("myMonster01", Monster.class);
System.out.println("myMonster01=" + myMonster01);
System.out.println(myMonster01 == myMonster02);//true. myMonster01和myMonster02是同一个对象
}
}
💖bean配置信息重用
在spring的ioc容器, 提供了一种继承的方式来实现bean配置信息的重用
1.src/beans.xml
增加如下配置
<!--配置Monster对象-->
<bean class="com.zzw.spring.bean.Monster" id="monster10"
p:monsterId="10"
p:name="蜘蛛侠"
p:skill="吐丝"
/>
<!--
1.配置Monster对象,
2.但是这个对象的属性值和id="monster10"对象的属性值一样
3.parent="monster10" 指定当前这个配置的对象的属性值从 id="monster10"的对象来
-->
<bean class="com.zzw.spring.bean.Monster" id="monster11" parent="monster10"/>
<!--配置Monster对象
1.如果bean指定了 abstract=true, 表示该bean对象, 是用于被继承
2.本身这个bean就不能被获取/实例化
-->
<bean class="com.zzw.spring.bean.Monster" id="monster12" abstract="true"
p:monsterId="12"
p:name="蜘蛛侠~"
p:skill="吐丝~"
/>
<bean id="monster13" class="com.zzw.spring.bean.Monster" parent="monster12"/>
2.测试: com/zzw/spring/test/SpringBeanTest.java
新增getBeanByExtends
方法
public class SpringBeanTest {
//通过继承, 配置bean
@Test
public void getBeanByExtends() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
Monster monster11 = ioc.getBean("monster11", Monster.class);
System.out.println("monster11=" + monster11);
Monster monster13 = ioc.getBean("monster13", Monster.class);
System.out.println("monster13=" + monster13);
}
}
💖bean创建顺序
在spring的ioc容器, 默认是按照配置的顺序创建bean对象
测试bean创建顺序
实验1
1.src/beans.xml
增加如下配置
<!--测试bean对象的创建顺序
1.在默认情况下, bean创建的顺序是按照配置顺序来的
2.但是如果我们增加了 depends-on="department01" 这时就会先创建id=department01这个对象
-->
<bean class="com.zzw.spring.bean.Student" id="student01"/>
<bean class="com.zzw.spring.bean.Department" id="department01"/>
2.测试: com/zzw/spring/test/SpringBeanTest.java
新增testBeanCreateOrder
方法
public class SpringBeanTest {
@Test
public void testBeanCreateOrder() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("ok~");
}
}
3.新增com.zzw.spring.bean.Department
public class Department {
public Department() {
System.out.println("Department构造器 被执行");
}
}
4.新增com.zzw.spring.bean.Student
public class Student {
public Student() {
System.out.println("Student构造器 被执行");
}
}
※
提示: 会先创建student01
这个bean对象, 然后创建department01
这个bean对象
5.运行结果
Student构造器 被执行
Department构造器 被执行
ok~
※
如果这样配置, 会先创建department01
对象, 再创建student01对象
<!--测试bean对象的创建顺序
1.在默认情况下, bean创建的顺序是按照配置顺序来的
2.但是如果我们增加了 depends-on="department01" 这时就会先创建id=department01这个对象
-->
<bean class="com.zzw.spring.bean.Student" id="student01" depends-on="department01"/>
<bean class="com.zzw.spring.bean.Department" id="department01"/>
6.运行结果
Department构造器 被执行
Student构造器 被执行
ok~
实验2
1.先看下面的配置, 请问两个bean创建的顺序是什么? 并分析执行流程, src/beans.xml
<!--配置MemberDaoImpl对象-->
<bean class="com.zzw.spring.dao.MemberDaoImpl" id="memberDao"/>
<bean class="com.zzw.spring.service.MemberServiceImpl" id="memberService">
<property name="memberDao" ref="memberDao"/>
</bean>
2.答案:
- 先创建
id=memberDao
- 再创建
id=memberService
- 调用
memberService.setMemberDao()
完成引用
3.测试: com/zzw/spring/test/SpringBeanTest.java
的testBeanCreateOrder
方法
public class SpringBeanTest {
@Test
public void testBeanCreateOrder() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("ok~");
}
}
4.运行结果:
MemberDaoImpl 构造器...
MemberServiceImpl 构造器被执行
setMemberDao()...
1.先看下面的配置, 请问两个bean创建的顺序是什么? 并分析执行流程, src/beans.xml
<bean class="com.zzw.spring.service.MemberServiceImpl" id="memberService">
<property name="memberDao" ref="memberDao"/>
</bean>
<!--配置MemberDaoImpl对象-->
<bean class="com.zzw.spring.dao.MemberDaoImpl" id="memberDao"/>
2答案:
- 先创建
id=memberService
- 再创建
id=memberDao
- 调用
memberService.setMemberDao()
完成引用
3.测试: com/zzw/spring/test/SpringBeanTest.java
的testBeanCreateOrder
方法
public class SpringBeanTest {
@Test
public void testBeanCreateOrder() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
System.out.println("ok~");
}
}
4.运行结果
MemberServiceImpl 构造器被执行
MemberDaoImpl 构造器...
setMemberDao()...
💖bean的单例和多实例
在spring的ioc容器中, 默认情况下是按照单例创建的. 即配置一个bean对象后, ioc容器只会创建一个bean对象
如果我们希望ioc容器配置的某个bean对象, 是以多个实例形式创建的. 则可以通过配置 scope=“prototype” 来指定
1.新建com.zzw.spring.bean.Cat
public class Cat {
private Integer id;
private String name;
public Cat() {
//getter, setter方法
}
2.src/beans.xml
增加如下配置
<!--配置Cat对象
1.在默认情况下, scope属性是 scope="singleton"
2.在ioc容器中, 只会有一个这样的bean对象
3.当程序员执行getBean时, 返回的是同一个对象
4.如果我们希望每次返回一个新的bean对象, 则可以这样配置 scope="prototype"
5.如果bean的配置是 scope="singleton" lazy-init="true" 这时, ioc容器就不会提前创建该对象
, 而是当执行getBean方法的时候, 才会创建对象
-->
<bean class="com.zzw.spring.bean.Cat" id="cat" scope="prototype" lazy-init="true">
<property name="id" value="100"/>
<property name="name" value="花喵"/>
</bean>
3.测试: com/zzw/spring/test/SpringBeanTest.java
增加testBeanScope
方法
//测试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);
}
使用细节
1)bean
默认是单例singleton
; 在启动容器时, bean
默认就会创建, 并放入到singletonObjects
2) 当<bean scope="prototype">
设置为多实例机制后, 该bean
是在getBean()
时被创建
3) 如果是单例singleton
, 同时希望在getBean
时才创建, 可以指定懒加载 lazy-init="true"(注意默认是false)
4) 通常情况下, lazy-init
就使用默认值false
. 在开发看来, 空间换时间是值得的, 除非有特殊要求
5) 如果scope="prototype"
, 这时你的lazy-init
属性的值不管是true
还是false
, 都是在getBean
的时候才创建这个对象
💖bean的生命周期
bean
对象创建是由JVM
完成的, 然后执行如下方法
- 执行构造器
- 执行
set
相关方法 - 调用
bean
的初始化方法(需要配置) - 使用
bean
- 当容器关闭的时候, 调用
bean
的销毁方法(需要配置)
●代码实现
1.新建com.zzw.spring.bean.House
public class House {
private String name;
public House() {
System.out.println("House构造器 被执行...");
}
public void setName(String name) {
System.out.println("House setName()=" + name);
this.name = name;
}
//解读
//1.这个方法是由程序员来编写的
//2.根据自己的业务逻辑来写.
//3.名字也不是固定的
public void init() {
System.out.println("House init()....");
}
//解读
//1.这个方法是由程序员来编写的
//2.根据自己的业务逻辑来写.
//3.名字也不是固定的
public void destroy() {
System.out.println("House destroy()...");
}
@Override
public String toString() {
return "House{" +
"name='" + name + '\'' +
'}';
}
}
2.配置src/beans.xml
<!--配置House对象, 演示整个bean的生命周期
解读
1.init-method="init" 指定bean的初始化方法, 在setter方法后执行
2.init方法执行的时机, 由spring容器控制
3.destroy-method="destroy" 指定bean的销毁方法, 在容器关闭的时候执行
4.destroy方法执行的时机, 由spring容器控制
-->
<bean class="com.zzw.spring.bean.House" id="house"
init-method="init" destroy-method="destroy">
<property name="name" value="上海豪宅"/>
</bean>
3.测试bean
的生命周期com.zzw.spring.test.SpringBeanTest
public class SpringBeanTest {
@Test
public void testBeanLife() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
House house = ioc.getBean("house", House.class);
System.out.println("house=" + house);
//关闭容器
//1.ioc的编译类型 ApplicationContext, 运行类型 ClassPathXmlApplicationContext
//2.因为ClassPathXmlApplicationContext 实现了 ConfigurableApplicationContext
//3.ClassPathXmlApplicationContext 是有close()的
//4.将ioc 转成ClassPathXmlApplicationContext, 再调用close()
//ioc.close()
//5.关闭ioc容器
((ClassPathXmlApplicationContext) ioc).close();
}
}
4.输出
House构造器 被执行...
House setName()=上海豪宅
House init()....
setMemberDao()...
house=com.zzw.spring.bean.House@327bcebd
House destroy()...
使用细节
1.初始化-init
方法和destroy
方法, 由程序员来指定
2.销毁方法就是当关闭容器时, 才会被调用