【spring】第二篇 bean实例化

news2024/10/6 5:56:34

对象已经能交给Spring的IOC容器来创建了,但是容器是如何来创建对象的呢?

就需要研究下bean的实例化过程,在这块内容中主要解决两部分内容,分别是

  • bean是如何创建的

  • 实例化bean的三种方式,构造方法,静态工厂实例工厂

在讲解这三种创建方式之前,我们需要先确认一件事:bean本质上就是对象,对象在new的时候会使用构造方法完成,那创建bean也是使用构造方法完成的。

基于这个知识点出发,我们来验证spring中bean的三种创建方式。

目录

一、构造方法实例化

优化

二、静态工厂实例化

使用工厂来创建对象

优化

三、实例工厂实例化

优化:FactoryBean使用

小结


一、构造方法实例化

优化

(1)准备需要被创建的类

准备一个BookDao和BookDaoImpl类,

package com.water.dao;

public interface BookDao {
  public void save();
}

在BookDaoImpl类中添加一个无参构造函数,并打印一句话,方便观察结果。 

package com.water.dao.impl;

import com.water.dao.BookDao;

public class BookDaoImpl implements BookDao {
  public BookDaoImpl() {
    System.out.println("book dao constructor is running ....");
  }

  public void save() {
    System.out.println("book dao save ...");
  }
}

(2)将类配置到Spring容器

<?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
    	id属性标示给bean起名字
    	class属性表示给bean定义类型
	-->
    <bean id="bookDao" class="com.water.dao.impl.BookDaoImpl"></bean>
</beans>

(3)运行程序,如果控制台有打印构造函数中的输出,说明Spring容器在创建对象的时候也走的是构造函数

(4)将构造函数改成private测试

运行程序,能执行成功,

说明内部走的依然是构造函数,能访问到类中的私有构造方法,显而易见Spring底层用的是反射。

(5)构造函数中添加一个参数测试

运行程序,程序会报错,说明Spring底层使用的是类的无参构造方法。

接下来,我们主要研究下Spring的报错信息,来学一学如阅读。

  • 错误信息从下往上依次查看,因为上面的错误大都是对下面错误的一个包装,最核心错误是在最下面

  • Caused by: java.lang.NoSuchMethodException: com.itheima.dao.impl.BookDaoImpl.<init>()

    • Caused by 翻译为引起,即出现错误的原因

    • java.lang.NoSuchMethodException:抛出的异常为没有这样的方法异常

    • com.itheima.dao.impl.BookDaoImpl.<init>():哪个类的哪个方法没有被找到导致的异常,<init>()指定是类的构造方法,即该类的无参构造方法

如果最后一行错误获取不到错误信息,接下来查看第二层:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.itheima.dao.impl.BookDaoImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.itheima.dao.impl.BookDaoImpl.<init>()

  • nested:嵌套的意思,后面的异常内容和最底层的异常是一致的

  • Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.itheima.dao.impl.BookDaoImpl]: No default constructor found;

    • Caused by: 引发

    • BeanInstantiationException:翻译为bean实例化异常

    • No default constructor found:没有一个默认的构造函数被发现

看到这其实错误已经比较明显,

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bookDao' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.itheima.dao.impl.BookDaoImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.itheima.dao.impl.BookDaoImpl.<init>()。

至此,关于Spring的构造方法实例化就已经学习完了,因为每一个类默认都会提供一个无参构造函数,所以其实真正在使用这种方式的时候,我们什么也不需要做。这也是我们以后比较常用的一种方式。

二、静态工厂实例化

使用工厂来创建对象

在讲这种方式之前,我们需要先回顾一个知识点是使用工厂来创建对象的方式:

  1. 准备一个OrderDao和OrderDaoImpl类
  2. 创建一个工厂类OrderDaoFactory并提供一个静态方法
  3. 编写AppForInstanceOrder运行类,在类中通过工厂获取对象
public interface OrderDao {
    public void save();
}

public class OrderDaoImpl implements OrderDao {
    public void save() {
        System.out.println("order dao save ...");
    }
}
//静态工厂创建对象
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        return new OrderDaoImpl();
    }
}
public class AppForInstanceOrder {
    public static void main(String[] args) {
        //通过静态工厂创建对象
        OrderDao orderDao = OrderDaoFactory.getOrderDao();
        orderDao.save();
    }
}

如果代码中对象是通过上面的这种方式来创建的,如何将其交给Spring来管理呢?

优化

这就要用到Spring中的静态工厂实例化的知识了,具体实现步骤为:

(1)在spring的配置文件application.properties中添加以下内容,

<?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
    	id属性标示给bean起名字
    	class属性表示给bean定义类型 工厂类的类全名
        factory-mehod:具体工厂类中创建对象的方法名
	-->
    <bean id="orderDao" class="com.water.dao.factory.OrderDaoFactory" factory-method="getOrderDao"/>
</beans>

(3)在AppForInstanceOrder运行类,使用从IOC容器中获取bean的方法进行运行测试,

package com.water;

import com.water.dao.BookDao;
import com.water.dao.OrderDao;
import com.water.dao.factory.OrderDaoFactory;
import com.water.server.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main( String[] args ) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");
        orderDao.save();

    }
}

运行后,可以查看到结果, 

这样的好处就是,在工厂的静态方法中,我们除了new对象还可以做其他的一些业务操作,这些操作必不可少。

public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        System.out.println("factory setup....");//模拟必要的业务操作
        return new OrderDaoImpl();
    }
}

 之前new对象的那种方式就无法添加其他的业务内容。

三、实例工厂实例化

package com.water.dao;

public interface OrderDao {
  public void save();
}

 

package com.water.dao.impl;

import com.water.dao.OrderDao;

public class OrderDaoImpl implements OrderDao {
  public void save() {
    System.out.println("order dao save ...");
  }
}
package com.water;

import com.water.dao.BookDao;
import com.water.dao.OrderDao;
import com.water.dao.factory.OrderDaoFactory;
import com.water.server.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main( String[] args ) {
        //创建实例工厂对象
        OrderDaoFactory OrderDaoFactory = new OrderDaoFactory();
        //通过实例工厂对象创建对象
        OrderDao OrderDao = OrderDaoFactory.getOrderDao();
        OrderDao.save();
    }
}

对于上面这种实例工厂的方式如何交给Spring管理呢?

优化:FactoryBean使用

(1)创建一个OrderDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法

FactoryBean接口其实会有三个方法,分别是:

T getObject() throws Exception;

Class<?> getObjectType();

default boolean isSingleton() {
		return true;
}

方法一:getObject(),被重写后,在方法中进行对象的创建并返回

方法二:getObjectType(),被重写后,主要返回的是被创建类的Class对象

方法三:没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认true,单例。

package com.water.dao.factory;

import com.water.dao.OrderDao;
import com.water.dao.impl.OrderDaoImpl;
import org.springframework.beans.factory.FactoryBean;

public class OrderDaoFactoryBean implements FactoryBean<OrderDao> {
  @Override
  public OrderDao getObject() throws Exception {
    return new OrderDaoImpl();
  }

  @Override
  public Class<?> getObjectType() {
    return OrderDao.class;
  }

  public boolean isSingleton() {
    return false;
  }
}

(2)在Spring的配置文件中进行配置

<?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
    	id属性标示给bean起名字
    	class属性表示给bean定义类型 工厂类的类全名
        factory-mehod:具体工厂类中创建对象的方法名
	-->
    <bean id="orderDao" class="com.water.dao.factory.OrderDaoFactoryBean"/>
</beans>

(3)运行类不用做任何修改,直接运行,

package com.water;

import com.water.dao.BookDao;
import com.water.dao.OrderDao;
import com.water.dao.factory.OrderDaoFactory;
import com.water.server.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main( String[] args ) {
        //创建实例工厂对象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        OrderDao orderDao1 = (OrderDao) ctx.getBean("orderDao");
        System.out.println(orderDao1);
        OrderDao orderDao2 = (OrderDao) ctx.getBean("orderDao");
        System.out.println(orderDao2);
    }
}

通过验证,会发现默认是单例,那如果想改成单例具体如何实现?只需要将isSingleton()方法进行重写,修改返回为false即可。

重新运行,查看结果,

从结果中可以看出现在已经是非单例了,但是一般情况下我们都会采用单例,也就是采用默认即可。所以isSingleton()方法一般不需要进行重写。

小结

通过这一节的学习,需要掌握:

(1)bean是如何创建的呢?

构造方法

(2)Spring的IOC实例化对象的三种方式分别是:

  • 构造方法(常用)

  • 静态工厂(了解)

  • 实例工厂(了解)

    • FactoryBean(实用)

这些方式中,重点掌握构造方法FactoryBean即可。

需要注意的一点是,构造方法在类中默认会提供,但是如果重写了构造方法,默认的就会消失,在使用的过程中需要注意,如果需要重写构造方法,最好把默认的构造方法也重写下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1792598.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[flutter]一键将YAPI生成的api.json文件转为需要的Dart Model类的脚本

目的&#xff1a; 根据YAPI接口平台生成的api.json接口文件&#xff0c;将接口数据转化为model类&#xff0c;生成对应的接口值类型文件。 发现&#xff1a; api.json文件导出&#xff1a; YAPi是一个接口管理平台&#xff0c;登录账号打开项目后&#xff0c;在点击数据管理…

DVWA-File Upload

Low 后端代码没有对上传的文件做任何过滤&#xff0c;所以可以上传一句话木马。 <?phpif( isset( $_POST[ Upload ] ) ) {// Where are we going to be writing to?$target_path DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";$target_path . basename( $_F…

安装MongoDB单副本说明

参考&#xff1a;https://blog.csdn.net/weixin_43464076/article/details/126509254 https://driverzhang.github.io/post/mongo%E5%BC%80%E5%90%AF%E4%BA%8B%E5%8A%A1%E4%B9%8B%E5%89%AF%E6%9C%AC%E9%9B%86%E9%87%87%E5%9D%91/ https://dev.to/alexalvess/getting-started-wi…

【CMake系列】05-静态库与动态库编译

在各种项目类型中&#xff0c;可能我们的项目就是一个 库 项目&#xff0c;向其他人提供 我们开发好的 库 (windows下的 dll /lib &#xff1b; linux下的 .a / .so)&#xff1b;有时候在一个项目中&#xff0c;我们对部分功能 打包成 库&#xff0c;方便在不同地方进行调用 静…

[Linux] 软链接使用绝对路径的重要性

文章目录 软链接使用绝对路径的重要性软链接路径复制软链接查看文件类型 软链接使用绝对路径的重要性 软链接路径 软链接必须指定绝对路径&#xff0c;否则复制软链接后&#xff0c;由于软链接的相对路径是从软链接所处位置开始解析的&#xff0c;因此使用相对路径的软链接可…

pip(3) install,完美解决 externally-managed-environment

前言 现象 在 Manjaro 22、Ubuntu 23.04、Fedora 38 等最新的linux发行版中运行pip install时&#xff0c;通常会收到一个错误提示&#xff1a;error: externally-managed-environment&#xff0c;即“外部管理环境”错误&#xff0c;但这不是一个 bug。 如果您想阅读&#x…

ISSCC论文详解-ISSCC.34.1 适用于高精度 AI 应用的 28nm 83.23TFLOPS/W POSIT

0 前言 本文将对存内计算前沿论文——ISSCC 2024 34.1进行分享介绍&#xff0c;包括背景介绍、解决方案和架构、主要创新点、最终结果对比四部分内容。 1 背景介绍 题目&#xff1a;《A 28nm 83.23TFLOPS/W POSIT-Based Compute-in-Memory Macro for High-Accuracy AI Appli…

【UML用户指南】-08-对基本结构建模-图

目录 1、41视图 2、术语和概念 3、结构图 &#xff08;1&#xff09;类图&#xff08;class diagram&#xff09;&#xff1a; &#xff08;2&#xff09;构件图&#xff1a;&#xff08;component diagram&#xff09; &#xff08;3&#xff09;组合结构图&#xff1a;…

掌握ChatGPT的正确打开方式

引言 随着人工智能技术的飞速发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域取得了显著的突破。其中&#xff0c;聊天生成预训练变换器&#xff08;ChatGPT&#xff09;作为一种新型的对话式AI模型&#xff0c;引起了广泛关注。本文将详细介绍ChatGPT的正确使用…

更换 RT-DETR 主干网络为 【ResNet-18】【ResNet-34】| 已支持 18/34/50/101/152 全系列尺寸

本专栏内容均为博主独家全网首发,未经授权,任何形式的复制、转载、洗稿或传播行为均属违法侵权行为,一经发现将采取法律手段维护合法权益。我们对所有未经授权传播行为保留追究责任的权利。请尊重原创,支持创作者的努力,共同维护网络知识产权。 之前这篇文章写过了添加【R…

ChatGPT基本原理详细解说

ChatGPT基本原理详细解说 引言 在人工智能领域&#xff0c;自然语言处理&#xff08;NLP&#xff09;一直是研究的热点之一。随着技术的发展&#xff0c;我们见证了从简单的聊天机器人到复杂的语言模型的演变。其中&#xff0c;ChatGPT作为一项突破性技术&#xff0c;以其强大…

实战:Zig 编写高性能 Web 服务(2)

1.1 编写 HTTP server 我们从python -m http.server 8000启动得到灵感&#xff0c;先确定好目标&#xff1a; 编写一个HTTP/1.1 http serverzig version 0.12.0 使用zig init搭建项目的前置工作你先自行搭建好&#xff0c;不会的翻看前面铺垫的章节熟悉zig的项目结构。 关键…

小米用田忌赛马的方式,逼得苹果降价超2000元应对,确实厉害

苹果的iPhone15降价2300多元&#xff0c;成为618的大热门&#xff0c;之前不少人士认为迫使苹果如此大幅度降价的原因是因为另一家手机企业的竞争&#xff0c;而日前有人士认为是小米用田忌赛马的方式&#xff0c;迫使苹果降价应对。 小米这次大幅度降价的手机并非是最新款的小…

设计模式-策略模式(行为型)

行为型-策略模式 了解策略模式 策略模式是一种行为型设计模式&#xff0c;在策略模式中定义了一系列算法或者策略&#xff0c;并将这些策略封装到独立的类中&#xff0c;使得可以相互替换。在使用时&#xff0c;可以指定响应的策略使用。 角色 策略接口&#xff1a;对于某种…

【计算机网络】计算机网络的概念

计算机网络的概念 导读一、计算机网络的概念1.1 个人理解1.2 通信设备与线路1.2.1 集线器1.2.2 交换机1.2.3 路由器 1.3 计算机网络的进一步理解1.4 互联网1.5 网的不同含义 二、计算机网络的不同定义2.1 广义观点2.2 资源共享观点2.3 用户透明性观点 结语 导读 大家好&#x…

【机器学习】基于OpenCV和TensorFlow的MobileNetV2模型的物种识别与个体相似度分析

在计算机视觉领域&#xff0c;物种识别和图像相似度比较是两个重要的研究方向。本文通过结合深度学习和图像处理技术&#xff0c;基于OpenCV和TensorFlow的MobileNetV2的预训练模型模&#xff0c;实现物种识别和个体相似度分析。本文详细介绍该实验过程并提供相关代码。 一、名…

【Python】ERROR: Could not find a version that satisfies the requirement

成功解决“ERROR: Could not find a version that satisfies the requirement”错误的全面指南 一、引言 在Python开发中&#xff0c;经常需要通过pip工具来安装各种依赖包。然而&#xff0c;有时在尝试安装某个包时&#xff0c;可能会遇到“ERROR: Could not find a version …

批量提取 Word 文档中的全部图片

步骤 1、打开 WinRAR 任选一个现成的压缩包双击打开 WinRAR &#xff0c;或从开始菜单打开 WinRAR 2、直接把要提取图片的 Word 文档拖入 WinRAR 菜单区域 1 → 2 → 3&#xff0c;WinRAR 资源管理目录中的 media 就是该 Word 文档所要提取的全部图片所在文件夹 按住&#x…

python书上的动物是啥

Python的创始人为Guido van Rossum。1989年圣诞节期间&#xff0c;在阿姆斯特丹&#xff0c;Guido为了打发圣诞节的无趣&#xff0c;决心开发一个新的脚本解释程序&#xff0c;做为ABC语言的一种继承。之所以选中Python作为程序的名字&#xff0c;是因为他是一个叫Monty Python…

CATIA进阶操作——创成式曲面设计入门(1)线架设计,三维点、直线、平面、曲线

目录 引出三维空间点生成三维直线三维平面三维曲线总结异形弹簧新建几何体草图编辑&#xff0c;画一条样条线进行扫掠&#xff0c;圆心和半径画出曲面上的螺旋线再次选择扫掠&#xff0c;圆心和半径 其他自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自定义信号重…