笔记大纲
-
集合属性(List&Map)
- List、数组和Set、 Map
-
FactoryBean(工厂Bean)
- 普通bean&工厂bean的区别
- 练习Demo1
-
bean的作用域(4种)
- 四大作用域简介(singleton、prototype)
- 练习Demo2
-
bean的生命周期
- 容器对bean的生命周期进行管理的过程(5个)
- bean的后置处理器(2个)
1.集合属性(List&Map)
集合是Java中提供的一种容器,可以用来存储多个数据,Collection 、Map层次结构中的根接口。
在Spring中可通过一组内置的XML标签来配置集合,比如
<list>
、<set>
、<map
>等。
1.1.List、数组和Set
配置java.util.List类型的属性,需指定<list>
标签,通过<value>
指定简单的常量值,通过<ref>
指定其他的Bean,通过<bean>
指定内置bean定义。数组、java.util.Array的定义与List一样,都使用<list>
,同样可以使用、
`标签。
创建员工类、部门类:
指定当前部门下的员工,员工类型为List,即部门与员工是一对多的关系!
package com.codinglin.beans;
import java.util.List;
//部门类
public class Department {
private Integer depId; //部门编号
private String depName; //部门名称
private List<Employee> employees;//员工
public Integer getDepId() {
return depId;
}
public void setDepId(Integer depId) {
this.depId = depId;
}
public String getDepName() {
return depName;
}
public void setDepName(String depName) {
this.depName = depName;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
@Override
public String toString() {
return "Department [depId=" + depId + ", depName=" + depName + "]";
}
}
package com.codinglin.beans;
//员工类
public class Employee {
private Integer empId;// 编号
private String name;// 姓名
private Integer gender; // 性别 0表示女,1表示男
private Double salary; // 薪水
public Employee() {
}
public Employee(Integer empId, String name, Integer gender) {
this.empId = empId;
this.name = name;
this.gender = gender;
}
public Employee(Integer empId, String name, Double salary) {
this.empId = empId;
this.name = name;
this.salary = salary;
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [empId=" + empId + ", name=" + name + ", gender=" + gender + ", salary=" + salary + "]";
}
}
配置spring-ioc.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 集合属性List -->
<bean id="deptList01" class="com.codinglin.beans.Department">
<property name="depId" value="5201"></property>
<property name="depName" value="互联网开发部"></property>
<property name="employees" >
<!--数组和set的使用方式和list类似 <array></array> <set></set>-->
<list>
<!-- <ref>指定对其它Bean的作用,通过<bean>指定内置bean的定义 -->
<ref bean="employee01"></ref>
<ref bean="employee02"></ref>
<ref bean="employee03"></ref>
</list>
</property>
</bean>
<bean id="employee01" class="com.codinglin.beans.Employee">
<property name="empId" value="20170001"></property>
<property name="name" value="林大侠"></property>
<property name="gender" value="1"></property>
<property name="salary" value="20000"></property>
</bean>
<bean id="employee02" class="com.codinglin.beans.Employee">
<property name="empId" value="20170002"></property>
<property name="name" value="神奇女侠"></property>
<property name="gender" value="0"></property>
<property name="salary" value="21000"></property>
</bean>
<bean id="employee03" class="com.codinglin.beans.Employee">
<property name="empId" value="20170003"></property>
<property name="name" value="钢铁侠"></property>
<property name="gender" value="1"></property>
<property name="salary" value="22000"></property>
</bean>
</beans>
测试类:
package com.codinglin.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.codinglin.beans.Department;
import com.codinglin.beans.Employee;
public class Test {
@SuppressWarnings("resource")
public static void main(String[] args) {
// 创建容器对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc.xml");
Department daptList = applicationContext.getBean("deptList01",Department.class);
System.out.println(daptList+","+daptList.getEmployees());
}
}
后台打印结果:
Department [depId=5201, depName=互联网开发部],[Employee [empId=20170001, name=林大侠, gender=1, salary=20000.0], Employee [empId=20170002, name=神奇女侠, gender=0, salary=21000.0], Employee [empId=20170003, name=钢铁侠, gender=1, salary=22000.0]]
1.2.Map属性
Java.util.Map通过<map>
标签来定义,
注意:必须要在标签里定义键!
将1.1.中Department类中部分属性、方法进行修改!
private List employees;//员工
public List getEmployees() {
return employees;
}
public void setEmployees(List employees) {
this.employees = employees;
}
在Department类添加Map类属性:
private Map<String, Employee> employeeMap; //员工Map集合属性
public Map<String, Employee> getEmployeeMap() {
return employeeMap;
}
public void setEmployeeMap(Map<String, Employee> employeeMap) {
this.employeeMap = employeeMap;
}
配置spring-ioc.xml文件:
<!-- 集合Map属性配置 -->
<bean id="deptMap01" class="com.codinglin.beans.Department">
<property name="depId" value="5202"></property>
<property name="depName" value="互联网测试部"></property>
<property name="employeeMap" >
<map>
<entry key="Jod5" value-ref="employee01"></entry>
<entry key="Jod3" value-ref="employee02"></entry>
</map>
</property>
</bean>
<bean id="employee01" class="com.codinglin.beans.Employee">
<property name="empId" value="20170001"></property>
<property name="name" value="林大侠"></property>
<property name="gender" value="1"></property>
<property name="salary" value="20000"></property>
</bean>
<bean id="employee02" class="com.codinglin.beans.Employee">
<property name="empId" value="20170002"></property>
<property name="name" value="神奇女侠"></property>
<property name="gender" value="0"></property>
<property name="salary" value="21000"></property>
</bean>
后台打印结果:
Department [depId=5202, depName=互联网测试部],{Jod5=Employee [empId=20170001, name=林大侠, gender=1, salary=20000.0], Jod3=Employee [empId=20170002, name=神奇女侠, gender=0, salary=21000.0]}
1.3.集合类型的Bean
上面1.1、1.2的xml文件配置时我们发现,集合对象只能配置在某个bean内部,集合配置不能重用,如果我们将集合bean的配置拿到外面来,给其它bean引用,那么我们就需要在配置集合类型的bean需要引入util名称空间!
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"<!--引入的命名空间-->
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 集合Map属性配置 -->
<bean id="deptMap01" class="com.codinglin.beans.Department">
<property name="depId" value="5202"></property>
<property name="depName" value="互联网测试部"></property>
<property name="employeeMap" ref="empMap" >
<!--数组和set的使用方式和list类似 <array></array> <set></set>-->
<!--
<map>
<entry key="Jod5" value-ref="employee01"></entry>
<entry key="Jod3" value-ref="employee02"></entry>
</map>
-->
</property>
</bean>
<util:map id="empMap">
<entry key="Jod5" value-ref="employee01"></entry>
<entry key="Jod3" value-ref="employee02"></entry>
</util:map>
<bean id="employee01" class="com.codinglin.beans.Employee">
<property name="empId" value="20170001"></property>
<property name="name" value="林大侠"></property>
<property name="gender" value="1"></property>
<property name="salary" value="20000"></property>
</bean>
<bean id="employee02" class="com.codinglin.beans.Employee">
<property name="empId" value="20170002"></property>
<property name="name" value="神奇女侠"></property>
<property name="gender" value="0"></property>
<property name="salary" value="21000"></property>
</bean>
</beans>
2.FactoryBean(工厂Bean)
Spring中bean有两种类型,一种是普通的bean、一种是工厂bean(FactoryBean
)。
2.1.普通bean&工厂bean的区别
工厂Bean返回的对象不是指定类的一个示例,返回的是该工厂bean的getObject()
方法所返回的对象,使我们程序员参与到bean对象的创建过程中。
工厂Bean必须要实现org.springframework.beans.factory.FactoryBean接口!!!
2.2.练习Demo1
创建普通bean–BlogInfo类:
package com.codinglin.beans;
public class BlogInfo {
private String blogName; //博客名
private String blogUrl; //博客地址
public BlogInfo() {
System.out.println("测试---BlogInfo无参函数被调用执行");
}
public String getBlogName() {
return blogName;
}
public void setBlogName(String blogName) {
this.blogName = blogName;
}
public String getBlogUrl() {
return blogUrl;
}
public void setBlogUrl(String blogUrl) {
this.blogUrl = blogUrl;
}
@Override
public String toString() {
return "BlogInfo [blogName=" + blogName + ", blogUrl=" + blogUrl + "]";
}
}
创建工厂bean–MyFactoryBean类:
package com.codinglin.beans;
import org.springframework.beans.factory.FactoryBean;
/*
* 工厂Bean
* Spring允许我们(开发者)参与到Bean对象的创建过程中,创建完对象之后,将对象交给Spring的容器进行管理
*/
public class MyFactoryBean implements FactoryBean<BlogInfo> {
public MyFactoryBean() {
System.out.println("MyFactoryBean类被调用执行");
}
/*
* 用于创建Bean的对象并将其返回给IOC容器
*/
@Override
public BlogInfo getObject() throws Exception {
BlogInfo blogInfo = new BlogInfo();
blogInfo.setBlogName("林大侠Coding日常");
blogInfo.setBlogUrl("https://coding0110lin.blog.csdn.net/");
return blogInfo;
}
/*
* 返回自己创建bean对象的类型
*/
@Override
public Class<?> getObjectType() {
return BlogInfo.class;
}
/*
* 创建的对象是否是单例
*/
@Override
public boolean isSingleton() {
return false;
}
}
配置spring-ioc.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 配置工厂Bean,容器返回的不是工厂bean的对象,而是返回工厂bean的getObject()返回的对象
id="blogInfo"表示真正返回的是数据bean的对象 (BlogInfo类)
-->
<bean id="blogInfo" class="com.codinglin.beans.MyFactoryBean">
</bean>
</beans>
测试类:
package com.codinglin.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.codinglin.beans.BlogInfo;
public class MainTest {
public static void main(String[] args) {
//创建容器对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-ioc.xml");
BlogInfo blogInfo = applicationContext.getBean("blogInfo",BlogInfo.class);
System.out.println(blogInfo);
}
}
后台打印结果:
3.bean的作用域(scope)
在Spring中,在元素的scope属性里设置bean的作用域,以此决定这个bean是单实例和多实例!默认情况下,Spring只为每个在IOC容器中声明的bean创建唯一的实例中,整个IOC容器范围内都能共享该实例:所有后续的getBean()调用和bean引用都返回这个唯一的bean实例,该作用域就被称为singleton,它也是默认的作用域!
3.1.四大作用域简介
作用域类型 | 说明 (创建时机) |
---|---|
singleton单例的(默认取值) | 对象在容器初始化的时候被创建,且仅会被创建一次,所以通过getBean从容器中获取对象的时候,获取是同一个! |
prototype多例的(原型) | 对象不会在容器初始化的时候被创建,每次在调用getBean方法从容器中获取对象的时候创建对象,所以每次在获取的对象不是同一个! |
request | 在一次请求范围有效,每次HTTP请求都会创建一个新的bean对象,适合于WebApplication环境。 |
session | 在一次会话范围有效,一次会话可以包含多个请求。同一个HTTP session 共享一个Bean,不同HTTP session 使用不同的Bean,适合于WebApplication环境。 |
3.2.练习Demo2
创建BlogInfo类:
package com.codinglin.beans;
public class BlogInfo {
private String blogName; //博客名
private String blogUrl;//博客地址
public BlogInfo() {
System.out.println("测试---BlogInfo无参函数被调用执行");
}
public String getBlogName() {
return blogName;
}
public void setBlogName(String blogName) {
this.blogName = blogName;
}
public String getBlogUrl() {
return blogUrl;
}
public void setBlogUrl(String blogUrl) {
this.blogUrl = blogUrl;
}
@Override
public String toString() {
return "BlogInfo [blogName=" + blogName + ", blogUrl=" + blogUrl + "]";
}
}
【1】singleton作用域下配置spring-scope.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<bean id="blogInfoTest" class="com.codinglin.beans.BlogInfo" scope="singleton">
<property name="blogName" value="林大侠Coding日常" ></property>
<property name="blogUrl" value="https://coding0110lin.blog.csdn.net/"></property>
</bean>
</beans>
测试类:
package com.codinglin.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.codinglin.beans.BlogInfo;
public class MainTest {
public static void main(String[] args) {
//创建容器对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");
BlogInfo blogInfo1 = applicationContext.getBean("blogInfoTest",BlogInfo.class);
System.out.println("=======测试blogInfo1实例======:"+blogInfo1);
BlogInfo blogInfo2 = applicationContext.getBean("blogInfoTest",BlogInfo.class);
System.out.println("=======测试blogInfo2实例======:"+blogInfo2);
//后续的getBean()调用和bean引用都返回这个唯一的bean实例--singleton作用域
System.out.print("=======singleton作用域下比较两个实例======:");
System.out.print(blogInfo1==blogInfo2);
}
}
后台打印结果:
【2】prototype作用域下仅配置spring-scope.xml文件:
<bean id="blogInfoTest" class="com.codinglin.beans.BlogInfo" scope="prototype">
<property name="blogName" value="林大侠Coding日常" ></property>
<property name="blogUrl" value="https://coding0110lin.blog.csdn.net/"></property>
</bean>
后台打印结果:
4.bean的生命周期
Spring IOC容器可以管理bean的生命周期,即在bean生命周期内特定的时间执行指定的任务。
4.1.容器对bean的生命周期进行管理的过程
阶段 | 说明 |
---|---|
阶段一 | 通过构造器或工厂方法创建bean实例 |
阶段二 | 通过set()方法为bean的属性赋值以及对其它的bean的引用 |
阶段三 | 调用bean的初始化方法 (需要手动指定) |
阶段四 | 使用bean |
阶段五 | 关闭容器时,调用bean的销毁方法 (需要手动指定) |
如有bean后置处理器,则是7个阶段,注意:
将bean实例传递给bean后置处理器的postProcessBeforeInitialization()方法
调用bean的初始化方法
将bean实例传递给bean后置处理器的postProcessAfterInitialization()方法
4.2.练习Demo3
创建BlogInfo类:
package com.codinglin.beans;
public class BlogInfo {
private String blogName; //博客名
private String blogUrl;//博客地址
public BlogInfo() {
System.out.println("测试1===Bean生命周期阶段①【通过构造方法创建bean对象】===");
}
public String getBlogName() {
return blogName;
}
public void setBlogName(String blogName) {
System.out.println("测试2===Bean生命周期阶段②【给对象的属性进行赋值操作】===");
this.blogName = blogName;
}
public String getBlogUrl() {
return blogUrl;
}
public void setBlogUrl(String blogUrl) {
this.blogUrl = blogUrl;
}
@Override
public String toString() {
return "BlogInfo [blogName=" + blogName + ", blogUrl=" + blogUrl + "]";
}
/**
* 初始化操作
*/
public void init() {
System.out.println("测试3===Bean生命周期阶段③【调用bean的初始化方法】===");
}
/**
* 销毁操作
*/
public void destroy() {
System.out.println("测试5===Bean生命周期阶段⑤【调用bean的销毁方法】===");
}
}
配置spring-lifecycle.xml文件:
正常配置bean时需要指定init-method
初始化方法和destroy-method
销毁的方法!
<?xml version="1.0" encoding="UTF-8"?>
<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">
<bean id="blogInfoTest" class="com.codinglin.beans.BlogInfo"
init-method="init" destroy-method="destroy">
<property name="blogName" value="林大侠Coding日常" ></property>
<!-- <property name="blogUrl" value="<<https://coding0110lin.blog.csdn.net/">>></property> 报错!!-->
<property name="blogUrl" >
<value><![CDATA[<<https://coding0110lin.blog.csdn.net>>]]></value>
</property>
</bean>
</beans>
测试类:
public class MainTest {
public static void main(String[] args) {
//创建容器对象
/*ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-lifecycle.xml");*/
//注意!!!!使用ApplicationContext的子接口
ConfigurableApplicationContext configurableApplicationContext = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
BlogInfo blogInfo = configurableApplicationContext.getBean("blogInfoTest",BlogInfo.class);
System.out.println("测试4===Bean生命周期阶段④【使用bean对象】===");
/*System.out.println(blogInfo);*/
configurableApplicationContext.close();
}
}
后台打印结果:
4.3.bean的后置处理器
bean后置处理器允许在调用初始化方法前后对bean进行额外的处理;
bean后置处理器对IOC容器里所有bean实例都会逐一处理,非单一实例;
bean后置处理器需要实现接口:
org.springframwork.beans.factory.config.BeanPostProcessor
;在初始化方法调用前后,Spring将把每一个bean实例分别传递给上面接口的方法:
postProcessBeforeInitalization(Object,String)
postProcessAftereInitalization(Object,String)
练习Demo
在初始化方法执行前,将博客地址中的<<>>替换为(())全部去掉
新建MyBeanPostProcessor类
package com.codinglin.beans;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor{
/*
* 在初始化方法执行之前执行,因为后置处理器对IOC容器里所有的bean实例逐一处理,所以参数为Object,不能使用泛型设计
* Object bean:表示当前正在被创建的bean对象
* String beanName :表示当前正在被创建的bean对象的名字,也就是配置文件中bean的id
*
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(" ========测试postProcessBeforeInitialization(之前)=======:"+bean+","+beanName);
BlogInfo bInfo=(BlogInfo)bean;
bInfo.setBlogUrl(bInfo.getBlogUrl().replaceAll("<", "{").replaceAll(">", "}"));
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(" ========测试postProcessAfterInitialization(之后)=======:"+bean+","+beanName);
return bean;
}
}
配置spring-lifecycle.xml文件添加:
<bean class="com.codinglin.beans.MyBeanPostProcessor"></bean>
后台打印结果:
☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!
☞本人博客:https://coding0110lin.blog.csdn.net/ 欢迎转载,一起技术交流吧!