网站首页 > 技术文章 正文
IOC基本概念
所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。
在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。 IOC 让程序员不在关注怎么去创建对象(new Object()),而是关注与对象创建之后的操作,把对象的创建、初始化、销毁等工作交给spring容器来做。
在Spring中,由Spring IoC容器管理的对象叫做bean。 bean就是由Spring IOC容器实例化、组装和管理的对象。
我们来看一下spring实例化bean的三种方式。
Spring实例化bean的三种方式
前面几节内容已经搭建了Spring源码工程,我们现在直接贴代码
构造函数实例化
- 创建Dog.java
package com.sxdx.entity;
/**
* @program: spring
* @description: dog
* @author: garnett
* @create: 2020-04-07 10:29
**/
public class Dog {
private String name;
private int age;
//默认构造器
public Dog() {
System.out.println("默认构造器 init");
}
//带参构造器
public Dog(String name, int age) {
System.out.println("带参构造器 init");
this.name = name;
this.age = age;
}
//get set ....
public void sayHello() {
System.out.println("大家好, 我叫" + getName() + ", 我今年" + getAge() + "岁了");
}
}
- 在resources 下创建dog-bean.xml 文件
<!-- 默认构造实例化 -->
<bean id="dog1" class="com.sxdx.entity.Dog" />
<!-- 指定构造器实例化 -->
<bean id="dog2" class="com.sxdx.entity.Dog">
<!-- 指定ApplicationContext造器参数 name对应构造器中参数名称 -->
<!-- 也可以通过指定参数类型,指定参数位置来注入属性-->
<constructor-arg name="name" value="哈士奇"/>
<constructor-arg name="age" value="3"/>
</bean>
- 测试类
XmlBeanFactory与ApplicationContext都是BeanFactory的子接口,实现了IOC功能。
ApplicationContext测试类:
public class DogController {
private ApplicationContext applicationContext;
@Before
public void initXmlBeanFactory() {
System.out.println("\n========测试方法开始=======\n");
applicationContext = new ClassPathXmlApplicationContext("dog-bean.xml");
}
@After
public void after() {
System.out.println("\n========测试方法结束=======\n");
}
@Test
public void test1() {
// 默认构造器
Dog dog1 = applicationContext.getBean("dog1", Dog.class);
Dog dog2 = applicationContext.getBean("dog2", Dog.class);
dog1.sayHello();
dog2.sayHello();
}
}
XmlBeanFactory测试类
public class DogController {
private XmlBeanFactory xmlBeanFactory;
@Before
public void initXmlBeanFactory() {
System.out.println("\n========测试方法开始=======\n");
xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("dog-bean.xml"));
}
@After
public void after() {
System.out.println("\n========测试方法结束=======\n");
}
@Test
public void test1() {
// 默认构造器
Dog dog1 = xmlBeanFactory.getBean("dog1", Dog.class);
Dog dog2 = xmlBeanFactory.getBean("dog2", Dog.class);
dog1.sayHello();
dog2.sayHello();
}
}
- 执行测试
我们执行DogController.test1,控制台打印结果如下:
========测试方法开始=======
带参构造器 init
默认构造器 init
大家好, 我叫null, 我今年0岁了
大家好, 我叫哈士奇, 我今年3岁了
========测试方法结束=======
XmlBeanFactory与ApplicationContext 区别:
ApplicationContext 是在启动spring容器时创建对象,我们在test1()方法开始打一个断点,在执行initXmlBeanFactory()方法后就会打印“带参构造器 init”,证明了我们的这个结论。
但是如果将ApplicationContext换成XmlBeanFactory,依然是在test1()方法中打断点,发现IOC容器在xmlBeanFactory.getBean()后才执行了实例化动作。
如果ApplicationContext想要实现和XmlBeanFactory相同的效果,需要使用 lazy-init="true"
<bean id="dog1" class="com.sxdx.entity.Dog" lazy-init="true"/>
静态工厂方法实例化
- 创建静态工厂
package com.sxdx.entity;
/**
* @program: spring
* @description: 静态工厂方法
* @author: garnett
* @create: 2020-04-08 15:34
**/
public class DogStaticFactory {
public DogStaticFactory() {
System.out.println("静态工厂实例化");
}
//静态工厂方法
public static Dog getInstances(){
return new Dog();
}
}
- 配置bean
<!--
利用静态工厂方法:
factory-method:静态工厂类的获取对象的静态方法
class:静态工厂类的全类名
-->
<bean id="dog3" class="com.sxdx.entity.DogStaticFactory" factory-method="getInstances"></bean>
- 测试
@Test
public void test2() {
Dog dog3 = applicationContext.getBean("dog3", Dog.class);
dog3.sayHello();
}
- 测试结果
========测试方法开始=======
默认构造器 init
大家好, 我叫null, 我今年0岁了
========测试方法结束=======
实例工厂方法实例化
- 创建实例工厂
package com.sxdx.entity;
/**
* @program: spring
* @description: 实例工厂方法
* @author: garnett
* @create: 2020-04-08 15:46
**/
public class DogInstanceFactory {
public DogInstanceFactory() {
System.out.println("实例工厂方法实例化");
}
//静态工厂方法
public Dog getInstances(){
return new Dog("德牧",5);
}
}
- 配置bean
<!--
利用实例工厂方法:
factory-bean:指定当前Spring中包含工厂方法的beanId
factory-method:工厂方法名称
注意:实例工厂方法实例化必须使用factory-bean来引入工厂bean,这点与静态工厂方法不同
-->
<bean id="dogInstanceFactory" class="com.sxdx.entity.DogInstanceFactory"/>
<bean id="dog4" factory-bean="dogInstanceFactory" factory-method="getInstances"/>
- 测试
@Test
public void test3() {
Dog dog4 = applicationContext.getBean("dog4", Dog.class);
dog4.sayHello();
}
- 测试结果
========测试方法开始=======
实例工厂方法实例化
带参构造器 init
大家好, 我叫德牧, 我今年5岁了
========测试方法结束=======
spring scope说明
spring配置文件中,以下2中写法等效,即默认单利模式
<bean id="dog1" class="com.sxdx.entity.Dog" />
<bean id="dog1" class="com.sxdx.entity.Dog" scope="singleton"/>
scope的常见选项有 singleton、prototype。singleton即是我们常说的单利,指在IOC容器中,这个bean只有一个实例。
验证如下:
<bean id="dog1" class="com.sxdx.entity.Dog" lazy-init="true" scope="singleton"/>
@Test
public void test1() {
// 默认构造器
Dog dog1 = applicationContext.getBean("dog1", Dog.class);
Dog dog2 = applicationContext.getBean("dog1", Dog.class);
System.out.println(dog1 == dog2);
}
返回结果为true。证明dog1和dog2是同一个实例
我们将scope改为prototype(多例模式):
<bean id="dog1" class="com.sxdx.entity.Dog" lazy-init="true" scope="prototype"/>
@Test
public void test1() {
// 默认构造器
Dog dog1 = applicationContext.getBean("dog1", Dog.class);
Dog dog2 = applicationContext.getBean("dog1", Dog.class);
System.out.println(dog1 == dog2);
}
返回结果为false。证明dog1和dog2是不是同一个实例。
注意:scope="prototype"时,spring容器启动的时候并不会创建对象,而是在得到 bean 的时候才会创建对象。
OK ,Spring IOC(控制反转)就讲到这里,下一节讲DI(依赖注入)
猜你喜欢
- 2024-10-15 BATJ面试必会之 Spring 篇(30题) 面试spring的面试题
- 2024-10-15 Spring知识点提炼 spring题
- 2024-10-15 springmvc的核心是啥,请求的流程怎么处理,控制反转怎么实现
- 2024-10-15 spring源码分析——spring大纲 spring源码分析和总结简书
- 2024-10-15 Spring思维导图,让Spring不再难懂(ioc篇)
- 2024-10-15 Spring框架介绍及使用 spring框架的使用步骤
- 2024-10-15 架构师必知必会:Java内置的控制反转机制-Service Provider
- 2024-10-15 轻松理解 Spirng IoC/控制方向反转
- 2024-10-15 什么是控制反转(ioc),通过解释总结告诉你
- 2024-10-15 搞透IOC,Spring IOC看这篇就够了
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)