课程信息
● 学习课程:Java工程师2022版
● 章节名称:Spring Ioc容器与Bean管理-Bean对象的作用域及生命周期
● 讲师:悟空
课程内容
bean scope属性用于决定对象何时被创建于作用范围
bean scope配置将影响容器内对象的数量
默认情况下bean会在Ioc容器创建后自动实例化,全局唯一
scope用法
<bean id="order1" class="com.imooc.spring.ioc.entity.Order" scope="prototype">
<property name="price" value="19.8"/>
<property name="quantity" value="1000"/>
</bean>
bean scope属性清单
singleton(单例默认值,每一个容器有且只有唯一的实例,实例被全局共享)
prototype(多例,每次使用时都是创建一个实例)
request(web环境下,每一次独立请求存在唯一实例)
session(web环境下,每一个session存在有唯一实例)
global session(portlet的web应用的共享session中)
websocket(每一次WebSocket连接中存在唯一实例)
singleton只会创建一次实例,不用占用过多的资源,会有线程安全问题
singleton在容器中式单例多线程执行,存在线程安全风险,在Ioc容器启动时实例化
prototype在容器中多实例,占用更多资源,不存在线程安全问题
在getBean()或对象注入时实例化
某一个属性在运行过程中是恒定不变的,那么使用单例模式,不会有线程安全的问题;某一个属性在运行过程中是一直在变化的,那么使用多例模式。
bean生命周期
Ioc容器准备初始化解析XML 对象实例化执行构造方法
为对象注入属性 调用init-method初始化方法
Ioc容器初始化完毕 执行业务代码
Ioc容器准备销毁 调用destroy-method
Ioc容器销毁完毕
<!-- init-method的方法是在设置完属性之后再执行的方法。 -->
<bean id="order1" class="com.imooc.spring.ioc.entity.Order" init-method="init" destory-method="destory">
<property name="price" value="19.8"/>
<property name="quantity" value="1000"/>
</bean>
public class Order{
private Float price;
private Integer quantity;
private Float total;
public Order() {
System.out.println("创建Order对象,"+this);
}
public void init() {
System.out.println("执行init()方法");
total = price * quantity;
}
public void pay(){
System.out.println("订单金额为:"+total);
}
public void destory() {
System.out.println("释放与订单对象相关的对象");
}
//get set...
}
public void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-*.xml");
Order order1 = context.getBean("order1",Order.class);
order1.pay();
//会自动调取destroy-method="destroy"里的方法
((ClassPathXmlApplicationContext) context).registerShutdownHook();
}
实现极简Ioc容器
所谓的IoC容器其本质就是Map键值对对象,将beanId与指定的对象进行绑定,使用了反射技术
1、获取本地的配置文件
2、读取配置文件
3、使用反射创建对象并且使用反射为对象的属性进行赋值的。
public class ClassPathXmlApplicationContext implements ApplicationContext{
private Map iocContainer = new HashMap();
public ClassPathXmlApplicationContext(){
try{
String filePath = this.getClass().getResource("/applicationContext.xml");
filePath = new URLDecoder().decode(filePath, "UTF-8");
SAXReader reader = new SAXReader();
Document document = reader.read(new File(filePath));
List<Node> beans = document.getRootElement().selectNodes("bean");
for(Node node: beans){
Element ele = (Element)node;
String id = ele.attributeValue("id");
String className = ele.attributeValue("class");
Class c = Class.forName(className);
Object obj = c.newInstance();
List<Node> properties = ele.selectNodes("property");
for(Node p : properties){
Element property = (Element)p;
String propName = property.attributeValue("name");
String propValue = property.attributeValue("value");
String setMethodName ="set"+propName.substring(0,1).toUpperCase() +propName.substring(1) ;
Sysetm.out.println("准备执行"+ setMethodName +"方法注入数据");
Method setMethod=c.getMethod(setMethodName,String.class);
setMethod.invoke(obj, propValue);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
public Object getBean(String beanId){
return iocContainer.get(beanId);
}
}
学习收获
学习了bean scope属性常见值,singleton和prototype的区别以及优缺点,以及学习bean的生命周期,通过代码实现了一个极简的Ioc容器
打卡截图