前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring 框架学习(三)---- IOC创建对象

Spring 框架学习(三)---- IOC创建对象

作者头像
RAIN7
发布2022-06-27 09:42:06
3850
发布2022-06-27 09:42:06
举报
文章被收录于专栏:RAIN7 de 编程之路

文章目录

Spring 框架学习(三)---- IOC创建对象的方式

  写完了第一个Spring的程序,相信已经对spring已经有所了解了,那么我们这节来了解一下,IOC是如何创建对象,什么时候创建对象的。

1、IOC 什么时候创建对象?

  Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext

我们先对两种进行介绍一下

BeanFactory(不推荐使用)

  BeanFactory 是基础类型的 IoC 容器,简单来说,BeanFactory 就是一个管理 Bean的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。

  BeanFactory 接口有多个实现类,最常见的是 XmlBeanFactory类,它是根据 XML 配置文件中的定义装配 Bean 的。

  创建 BeanFactory 实例时,需要提供 Spring 所管理容器的详细配置信息,这些信息通常采用 XML 文件形式管理。其加载配置信息的代码具体如下所示

代码语言:javascript
复制
BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D://applicationContext.xml"));

ApplicationContext

  ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文,它不仅提供了 BeanFactory 的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持。

  ApplicationContext 接口有两个常用的实现类,具体如下。

1)ClassPathXmlApplicationContext(重点认识)

  该类从类路径 ClassPath 中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作,具体如下所示。

代码语言:javascript
复制
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);

2)FileSystemXmlApplicationContext(知道就行)

  该类从指定的文件系统路径中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作,具体如下所示。

代码语言:javascript
复制
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation);

  在使用 Spring 框架时,可以通过实例化其中任何一个类创建 Spring 的 ApplicationContext 容器。

两者区别

BeanFactory

  BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化;

ApplicationContext

  ApplicationContext在启动的时候就把所有的Bean全部实例化了。

  所以我们可以得知,对象在什么时候创建,我们使用的是ApplicationContext,所以在Spring启动的时候就已经把所有的Bean对象给创建好了。

优缺点,各有利弊

  • 延迟实例化的优点:(BeanFactory)

先快后慢

  应用启动的时候占用资源很少;对资源要求较高的应用,比较有优势;

  • 不延迟实例化的优点: (ApplicationContext)

先慢后快

1.  所有的Bean在启动的时候都加载,在后续的操作中系统运行的速度快;

2.  在启动的时候所有的Bean都加载了,我们就能在系统启动的时候,尽早的发现系统中的配置问题

2、IOC 如何创建对象?

(1)我们给实体类中加了一个无参构造方法、还有带一个参数的构造方法。

代码语言:javascript
复制
package com.kuang.pojo;

public class Hello {
    private String str;

    public Hello() {
        System.out.println("这是一个无参构造!");
    }

    public Hello(String str) {
        this.str = str;
        System.out.println("这是一个带有一个参数的构造器!");
    }

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

(2)配置xml中的bean

代码语言:javascript
复制
<?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="hello" class="com.kuang.pojo.Hello">
        <property name="str" value="Hello Spring!"/>
    </bean>
</beans>

(3)编写业务层代码

代码语言:javascript
复制
package com.kuang.service;

import com.kuang.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class HelloService {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Hello hello = context.getBean("hello", Hello.class);
        System.out.println(hello);
    }
}

运行之后,默认调用的是无参的构造方法

在这里插入图片描述
在这里插入图片描述

我们可以得到一个结论:

如果不做专门的配置,那么bean是通过无参构造来进行创建对象的

如果想要对实体类进行有参构造的创建怎么实现呢?

IOC创建有参构造器对象的三种方式

这三种方式同样,推荐大家一定要上spring的官方进行查看,说的非常清楚了。

(1)根据参数下标进行赋值(推荐)

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>
  • index 代表构造参数的下标,从0开始
  • value 代表设置的值

在文档中说明,通过index(从0开始),对对应位置的构造参数进行设置value,即可通过有参构造器构建对象

(1)写一个User类,中有四个构造函数,有参,一个构造参数…,

代码语言:javascript
复制
package com.kuang.pojo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@Getter
@Setter
@ToString
public class User {
    private int id;
    private String userName;
    private String password;

    public User() {
        System.out.println("无参构造进行创建对象!");
    }

    public User(int id) {
        this.id = id;
        System.out.println("一个参数构造的进行创建对象");
    }

    public User(int id, String userName) {
        this.id = id;
        this.userName = userName;
        System.out.println("两个参数构造进行创建对象");
    }

    public User(int id, String userName, String password) {
        this.id = id;
        this.userName = userName;
        this.password = password;
        System.out.println("三个参数构造进行创建对象");
    }


}

(2)xml文件通过下标的方式配置bean,只设置了一个参数

代码语言:javascript
复制
<?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="user" class="com.kuang.pojo.User">
     <constructor-arg index="0" value="1"/>
 </bean>

</beans>

(3)然后通过ApplicationContext启动Spring容器

代码语言:javascript
复制
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        User user = context.getBean("user",User.class);
    }

(4)运行结果

在这里插入图片描述
在这里插入图片描述

(2)根据参数类型进行赋值(不推荐)

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>
  • type 构造参数的类型,如果是普通类型直接写int、double,如果是引用类型写全限定名
  • value 设置的参数值

在文档中说明,通过type(引用类型要写全限定名),对对应类型的构造参数进行设置value,即可通过有参构造器构建对象

有一个问题,如果多个构造参数都是同一个类型呢?

答:会根据标签的顺序对同一类型的参数进行从前到后赋值。

(1)前面的User类不变

(2)通过类型配置bean创建对象

代码语言:javascript
复制
<?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="user" class="com.kuang.pojo.User">
     <constructor-arg type="int" value="1"/>
     <constructor-arg type="java.lang.String" value="userName"/>
     <constructor-arg type="java.lang.String" value="password"/>
 </bean>

</beans>

(3)启动Spring,如上

(4)查看运行结果

在这里插入图片描述
在这里插入图片描述

(3)根据参数名进行赋值(推荐)

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
<beans>
    <bean id="thingOne" class="x.y.ThingOne">
        <constructor-arg ref="thingTwo"/>
        <constructor-arg ref="thingThree"/>
    </bean>

    <bean id="thingTwo" class="x.y.ThingTwo"/>

    <bean id="thingThree" class="x.y.ThingThree"/>
</beans>
  • name 构造参数的类型,如果是普通类型直接写int、double,如果是引用类型写全限定名
  • value/ref 设置的参数值

这种方式看着非常直观,非常容易理解,这种方式与设置类中的属性是一样的

其他都不变,xml配置文件通过构造参数名字来创建对象

代码语言:javascript
复制
<?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="user" class="com.kuang.pojo.User">
    <constructor-arg name="id" value="1"/>
     <constructor-arg name="userName" value="root"/>
     <constructor-arg name="password" value="123456"/>
 </bean>

</beans>

查看运行结果

在这里插入图片描述
在这里插入图片描述

3、IOC容器存储一个bean,取出多个对象是否相同?

(1)编写实体类User

代码语言:javascript
复制
package com.kuang.pojo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class User {
    private int id;
    private String userName;
    private String password;

}

(2)在xml配置文件中装配

代码语言:javascript
复制
<?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="user" class="com.kuang.pojo.User"/>

</beans>

(3)根据同一个bean取出多个对象

代码语言:javascript
复制
  public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        User user = context.getBean("user",User.class);
        User user2 = context.getBean("user",User.class);
        System.out.println(user==user2);

    }

(4)运行结果

在这里插入图片描述
在这里插入图片描述

结论: IOC默认创建对象都是单例模式的,一个类只能拿到一个实例

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • Spring 框架学习(三)---- IOC创建对象的方式
    • 1、IOC 什么时候创建对象?
      • BeanFactory(不推荐使用)
      • ApplicationContext
      • 两者区别
      • 优缺点,各有利弊
    • 2、IOC 如何创建对象?
      • (1)根据参数下标进行赋值(推荐)
      • (2)根据参数类型进行赋值(不推荐)
      • (3)根据参数名进行赋值(推荐)
    • 3、IOC容器存储一个bean,取出多个对象是否相同?
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档