Spring 框架基础(02):Bean的生命周期,作用域,装配总结
程序员文章站
2023-04-05 16:21:35
本文源码: "GitHub·点这里" || "GitEE·点这里" 一、装配方式 Bean的概念:Spring框架管理的应用程序中,由Spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为Bean对象。 1、XML格式装配 Spring最传统的Bean的管理方式。 配置方式 测试 ......
本文源码:github·点这里 || gitee·点这里
一、装配方式
bean的概念:spring框架管理的应用程序中,由spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为bean对象。
1、xml格式装配
spring最传统的bean的管理方式。
- 配置方式
<bean id="userinfo" class="com.spring.mvc.entity.userinfo"> <property name="name" value="cicada" /> </bean>
- 测试代码
applicationcontext context01 = new classpathxmlapplicationcontext("/bean-scan-02.xml"); userinfo userinfo = (userinfo)context01.getbean("userinfo") ; system.out.println(userinfo.getname());
2、注解扫描
在实际开发中:通常使用注解 取代 xml配置文件。
- 常见注解
@component <==> <bean class="class"> @component("id") <==> <bean id="id" class="class"> @repository :mvc架构中dao层bean的注解 @service:mvc架构中service层bean的注解 @controller:mvc架构中controller层bean的注解
- 使用案例
// 1、注解代码块 @component("infoservice") public class infoserviceimpl implements infoservice { @override public void printname(string name) { system.out.println("name:"+name); } } // 2、配置代码块 @componentscan // 组件扫描注解 public class beanconfig { }
- 测试代码
@runwith(springjunit4classrunner.class) @contextconfiguration(classes = beanconfig.class) public class test01 { @autowired private infoservice infoservice ; @test public void test1 (){ infoservice.printname("cicada"); system.out.println(infoservice==infoservice); } }
3、xml配置扫描
上面使用 componentscan 注解,也可在配置文件进行统一的配置,效果相同,还简化代码。
<context:component-scan base-package="com.spring.mvc" />
4、java代码装配
这种基于configuration注解,管理bean的创建,在springboot和springcloud的框架中,十分常见。
- 配置类代码
@configuration // 配置类注解 public class userconfig { @bean public userinfo userinfo (){ system.out.println("userinfo..."); return new userinfo() ; } }
- 测试代码
@runwith(springjunit4classrunner.class) @contextconfiguration(classes = userconfig.class) public class test03 { @autowired private userinfo userinfo ; @autowired private userinfo userinfo1 ; @test public void test1 (){ /* * userinfo... * true */ system.out.println(userinfo==userinfo1); } }
二、属性值设置
上面是bean的装配几种常见方式,下面来看看bean属性值设置,这里就基于xml配置的方式。
1、基础类型和集合
- 配置代码
<!-- 配置employee公共属性 --> <bean id="emp1" class="com.spring.mvc.entity.employee"> <property name="name" value="cicada" /> <property name="id" value="1" /> </bean> <bean id="emp2" class="com.spring.mvc.entity.employee"> <property name="name" value="smile" /> <property name="id" value="2" /> </bean> <!-- 配置department属性 --> <bean id="department" class="com.spring.mvc.entity.department"> <!-- 普通属性值的注入 --> <property name="name" value="it部门" /> <!-- 给数组注入值 --> <property name="empname"> <list> <value>empname1</value> <value>empname2</value> <value>empname3</value> </list> </property> <!-- 给list注入值:可以存放相同的值 --> <property name="emplist"> <list> <ref bean="emp1"/> <ref bean="emp2"/> <ref bean="emp1"/> </list> </property> <!-- 配置set属性,相同的对象会被覆盖 --> <property name="empset"> <set> <ref bean="emp1"/> <ref bean="emp2"/> <ref bean="emp1"/> </set> </property> <!-- 配置map属性,key相同的话,后面的值会覆盖前面的 --> <property name="empmap"> <map> <entry key="1" value-ref="emp1" /> <entry key="2" value-ref="emp2" /> <entry key="2" value-ref="emp1" /> </map> </property> <!-- 配置属性集合 --> <property name="pp"> <props> <prop key="pp1">hello</prop> <prop key="pp2">world</prop> </props> </property> </bean>
- 测试代码
public class test05 { @test public void test01 (){ applicationcontext context = new classpathxmlapplicationcontext("/bean-value-03.xml"); department department = (department) context.getbean("department"); system.out.println(department.getname()); system.out.println("--------------------->string数组"); for (string str : department.getempname()){ system.out.println(str); } system.out.println("--------------------->list集合"); for (employee smp : department.getemplist()){ system.out.println(smp.getid()+":"+smp.getname()); } system.out.println("--------------------->set集合"); for (employee emp : department.getempset()){ system.out.println(emp.getid()+":"+emp.getname()); } system.out.println("--------------------->map集合"); for (map.entry<string, employee> entry : department.getempmap().entryset()){ system.out.println(entry.getkey()+":"+entry.getvalue().getname()); } system.out.println("--------------------->properties"); properties pp = department.getpp(); system.out.println(pp.get("pp1")); system.out.println(pp.get("pp2")); } }
2、配置构造函数
根据配置的参数个数和类型,去映射并加载bean的构造方法。
- 配置代码
<!-- 这里配置2个参数,所有调用2个参数的构造函数 --> <bean id="employee" class="com.spring.mvc.entity.employee"> <constructor-arg index="0" type="java.lang.string" value="cicada"/> <constructor-arg index="1" type="int" value="1"/> </bean>
- 测试代码
public class test06 { @test public void test01 (){ applicationcontext context = new classpathxmlapplicationcontext("/bean-value-04.xml"); employee employee = (employee) context.getbean("employee"); system.out.println(employee.getid()+":"+employee.getname()); } }
3、配置继承关系
- 配置代码
<!-- 配置父类信息 --> <bean id="student" class="com.spring.mvc.entity.student"> <property name="name" value="spring" /> <property name="age" value="22" /> </bean> <!-- 配置子类信息 --> <bean id="grade" class="com.spring.mvc.entity.grade"> <!-- 覆盖 --> <property name="name" value="summer" /> <property name="degree" value="大学" /> </bean>
- 测试代码
public class test07 { @test public void test01 (){ applicationcontext context = new classpathxmlapplicationcontext("/bean-value-05.xml"); grade grade = (grade) context.getbean("grade"); /* summer;0;大学 */ system.out.println(grade.getname()+";"+grade.getage()+";"+grade.getdegree()); } }
三、作用域
作用域:用于确定spring创建bean实例个数,比如单例bean,原型bean,等等。
类型 | 说明 |
---|---|
singleton | ioc容器仅创建一个bean实例,ioc容器每次返回的是同一个单例bean实例,默认配置。 |
prototype | ioc容器可以创建多个bean实例,每次返回的bean都是新的实例。 |
request | 每次http请求都会创建一个新的bean,适用于webapplicationcontext环境。 |
session | 同一个http session共享一个bean实例。不同http session使用不同的实例。 |
global-session | 同session作用域不同的是,所有的session共享一个bean实例。 |
四、生命周期
在spring框架中bean的生命周期非常复杂,过程大致如下:实例化,属性加载,初始化前后管理,销毁等。下面基于一个案例配置,会更加的清楚。
1、编写beanlife类
public class beanlife implements beannameaware { private string name ; public string getname() { return name; } public void setname(string name) { system.out.println("设置名称:"+name); this.name = name; } @override public void setbeanname(string value) { system.out.println("beannameaware..setname:"+value); } public void initbean() { system.out.println("初始化bean.."); } public void destroybean() { system.out.println("销毁bean.."); } public void usebean() { system.out.println("使用bean.."); } @override public string tostring() { return "beanlife [name = " + name + "]"; } }
2、定制加载过程
实现beanpostprocessor接口。
public class beanlifepostprocessor implements beanpostprocessor { // 初始化之前对bean进行增强处理 @override public object postprocessbeforeinitialization(object obj, string beanname) throws beansexception { system.out.println("初始化之前..."+beanname); return obj ; } // 初始化之后对bean进行增强处理 @override public object postprocessafterinitialization(object obj, string beanname) throws beansexception { system.out.println("初始化之后..."+beanname); // 改写bean的名称 if (obj instanceof beanlife){ beanlife beanlife = (beanlife)obj ; beanlife.setbeanname("mybeanlifetwo"); return beanlife ; } return obj ; } }
3、配置文件
<!-- 加载bean的处理器 --> <bean class="com.spring.mvc.beanlifepostprocessor" /> <!-- 指定初始化和销毁方法 --> <bean id="beanlife" class="com.spring.mvc.entity.beanlife" init-method="initbean" destroy-method="destroybean"> <property name="name" value="mybeanlifeone" /> </bean>
4、测试过程
- 测试代码
public class test08 { @test public void test01 (){ applicationcontext context = new classpathxmlapplicationcontext("/bean-value-06.xml"); beanlife beanlife = (beanlife) context.getbean("beanlife"); system.out.println("测试结果beanlife:"+beanlife.getname()) ; beanlife.usebean(); // 关闭容器 ((abstractapplicationcontext) context).close(); } }
- 输出结果
1、设置名称:mybeanlifeone 2、beannameaware..setname:beanlife 3、初始化之前...beanlife 4、初始化bean.. 5、初始化之后...beanlife 6、beannameaware..setname:mybeanlifetwo 7、测试结果beanlife:mybeanlifeone 8、使用bean.. 9、销毁bean..
这里梳理bean的生命周期,过程十分清晰。
五、源代码地址
github·地址 https://github.com/cicadasmile/spring-mvc-parent gitee·地址 https://gitee.com/cicadasmile/spring-mvc-parent