Spring03——基于xml的Spring应用

Spring开发中主要对Bean的配置

Bean的常用配置一览如下:

Xml配置方式功能描述
<bean id="" class="">Bean的id和全限定名配置
<bean name="">通过name设置Bean的别名,通过别名也能直接获取到Bean实例
<bean scope="">Bean的作用范围,BeanFactory作为容器时取值singleton和prototype
<bean lazy-init="">Bean的实例化时机,是否延迟加载。BeanFactory作为容器时无效
<bean init-method="">Bean实例化后自动执行的初始化方法,method指定方法名
<bean destroy-method="">Bean实例销毁前的方法,method指定方法名
<bean autowire="byType">设定自动注入模式,常用的有按类型byType,按名称byName
<bean factory-bean="" factory-method=""/>指定哪个工厂Bean的哪个方法来完成Bean的创建

 Bean取别名

通过name取别名,同样可以获取实例

 

Bean的范围配置

默认情况下,单纯的Spring环境Bean的作用范围有两个(scope配置):Singleton和Prototype

  • singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例;
  • prototype(默认):原型,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。

Bean的延迟加载

当lazy-init设置为true时为延迟加载,也就是当Spring容器创建的时候,不会立即创建Bean实例等待用到时在创建Bean实例并存储到单例池中去,后续在使用该Bean直接从单例池获取即可本质上该Bean还是单例

<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl" lazy-init="true"/> 
        ApplicationContext applicationContext = new                 
        ClassPathXmlApplicationContext("applicationContext.xml");
        // lazy-init="true"开启,那么只有调用getBean时才会创建Bean实例,而不是之前创建容器时
        UserService userService = (UserService) applicationContext.getBean("aaa");
        System.out.println(userService);

Bean的初始化和销毁方法配置

Bean在被实例化后,可以通过指定的初始化方法完成一些初始化的操作,Bean在销毁之前也可以执行指定的销毁方法完成一些操作。

<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"
 init-method="init" destroy-method="destroy"/>

定义init方法和destory方法 

public class UserDaoImpl implements UserDao {  
    public UserDaoImpl() { System.out.println("UserDaoImpl创建了..."); }  
    public void init() { System.out.println("初始化方法..."); }  
    public void destroy() { System.out.println("销毁方法..."); }  
}

 

 由上图可见,并没有显示销毁方法

关闭容器Bean就销毁,否则bean销毁不了,因为关闭容器是在虚拟机结束之前执行,如果没有close,那么虚拟机关闭,什么都没有了。 

扩展:除此之外,我们还可以通过实现 InitializingBean 接口,完成一些Bean的初始化操作,如下:

public class UserDaoImpl implements UserDao, InitializingBean {  
    public UserDaoImpl() { System.out.println("UserDaoImpl创建了..."); }  
    
    public void init() { System.out.println("初始化方法..."); }  
    
    public void destroy() { System.out.println("销毁方法..."); }  
    
    // 执行时机早于init-method配置的方法  
    @Override
    public void afterPropertiesSet() throws Exception {  
        System.out.println("InitializingBean...");  
    }  
}

  使用InitializingBean , DisposableBean接口(推荐)

 这样就不需要再Bean标签里写init和destory了

Bean的生命周期 

下面是Spring Bean生命周期示例,包括创建、初始化和销毁的代码。

Bean类

创建一个简单的Bean类,并定义初始化和销毁方法:

import org.springframework.beans.factory.InitializingBean;  
import org.springframework.beans.factory.DisposableBean;  

public class MyBean implements InitializingBean, DisposableBean {  

    private String name;  
    private String version;  
    private String author;  

    public MyBean() {  
        System.out.println("1. 创建对象 - 构造器");  
    }  

    public void setName(String name) {  
        this.name = name;  
        System.out.println("设置属性 - name: " + name);  
    }  

    public void setVersion(String version) {  
        this.version = version;  
        System.out.println("设置属性 - version: " + version);  
    }  

    public void setAuthor(String author) {  
        this.author = author;  
        System.out.println("设置属性 - author: " + author);  
    }  

    @Override  
    public void afterPropertiesSet() throws Exception {  
        System.out.println("4. 执行Bean初始化方法 (afterPropertiesSet)");  
        System.out.println("Bean 信息 - Name: " + name + ", Version: " + version + ", Author: " + author);  
    }  

    @Override  
    public void destroy() throws Exception {  
        System.out.println("关停 Bean - 销毁方法 (destroy)");  
    }  

    public void performTask() {  
        System.out.println("执行业务操作 - " + name);  
    }  
}

Spring配置

使用XML配置来定义Bean,指定其由接口管理的初始化和销毁方法:

 <bean id="myBean" class="com.example.MyBean">  
        <property name="name" value="Spring Bean"/>  
        <property name="version" value="1.0"/>  
        <property name="author" value="John Doe"/>  
    </bean>  

主程序

创建Application类,加载Spring上下文,使用Bean并关闭上下文以触发销毁阶段:

import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class Application {  

    public static void main(String[] args) {  
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  

        MyBean myBean = (MyBean) context.getBean("myBean");  
        // 执行myBean的一些业务

        // 关闭上下文,触发销毁方法  
        ((ClassPathXmlApplicationContext) context).close();  
    }  
}

Bean的3种实例化

构造方式实例化:底层通过构造方法对Bean进行实例化  

工厂方式实例化:底层通过调用自定义的工厂方法对Bean进行实例化

Bean的实例化配置

构造方式实例化Bean又分为无参构造方法实例化和有参构造方法实例化,Spring中配置的<bean>几乎都是无参构造方式,但处不在赘述。下面讲解有参构造方法实例化Bean

// 有参构造方法  
public UserDaoImpl(String name){  
}

在实现类文件里默认有一个无参构造器,如果写一个有参构造器,那么jvm识别不到无参构造器会报错 。

在实现类文件中写入有参构造方法后,有参构造在实例化Bean时,需要参数的注入,通过<constructor-arg>标签(name表示传入的变量名,value表示变量名对应的传入参数,在bean标签里传入即可,调用getBean会自动添加进去,如果有多个参数,就多个<constructor-arg>标签),嵌入在<bean>标签内部提供构造参数,如下:

        <!--上面的有参构造器对应的xml配置-->
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl">  
    <constructor-arg name="name" value="haohao"/>  
</bean>

静态工厂创建对象

factory-method 创建对象:即在xml的bean标签里配置factory-method = "userDao",那么创建getBean对象返回的不是class对应的类的实例,而是class类里面userDao静态方法返回的实例

<bean id="userDao1" class="com.itheima.factory.MyBeanFactory1"
 factory-method="userDao"></bean>
public class MyBeanFactory1 {
    public static UserDao userDao(){
        // bean之前可以进行其他的业务逻辑操作
        return new UserDaoImpl();
    }
}

实例工厂创建对象

<--实例化一个工厂-->
<bean id="myBeanFactory2" class="com.itheima.factory.MyBeanFactory2"
 lazy-init="true"></bean>
<--factory-bean是代指工厂-->
<bean id="userDao2" factory-bean="myBeanFactory2" 
factory-method="userDao" lazy-init="true"></bean>

public class MyBeanFactory2 {
// 实例方法返回对象
    public UserDao userDao(){
        return new UserDaoImpl();
    }
}

FactoryBean创建(实用)

package com.itheima.factory;

import com.itheima.dao.UserDao;
import com.itheima.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.FactoryBean;

public class UserDaoFactoryBean implements FactoryBean {
    // 返回bean
    @Override
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }
    // 返回Bean的类型
    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }
// 是否为单例
  @Override
    public boolean isSingleton() {
        return true;
    }
}
<bean id="UserDao" class="com.itheima.factory.UserDaoFactoryBean"></bean>

 依赖注入的方式

一、setter方法注入引用类型/简单类型(下面以同时注入这两种类型为例)

假设我们有一个Product类,它包含一个简单类型属性(如productId)和一个引用类型属性(如Category)。

1. 定义Category

首先,定义Category类,表示产品类别:

public class Category {  
    private String categoryName;  

    // Setter方法  
    public void setCategoryName(String categoryName) {  
        this.categoryName = categoryName;  
    }  

    // Getter方法  
    public String getCategoryName() {  
        return categoryName;  
    }  

    public void displayInfo() {  
        System.out.println("Category: " + categoryName);  
    }  
}

2. 定义Product

接下来,定义一个Product类,它具有一个简单类型的productId和一个引用类型的Category

public class Product {  
    private String productId; // 简单类型  
    private Category category; // 引用类型  

    // Setter方法注入  
    public void setProductId(String productId) {  
        this.productId = productId;  
    }  

    public void setCategory(Category category) {  
        this.category = category;  
    }  

    public void displayProductInfo() {  
        System.out.println("Product ID: " + productId);  
        if (category != null) {  
            category.displayInfo();  
        } else {  
            System.out.println("No category information available.");  
        }  
    }  
}

3. Spring配置文件

在Spring的XML配置文件中,定义CategoryProduct的Bean,并同时注入简单类型和引用类型:

<!-- applicationContext.xml -->  
<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="category" class="com.example.Category">  
        <property name="categoryName" value="Electronics"/> <!-- 注入简单类型 -->  
    </bean>  

    <bean id="product" class="com.example.Product">  
        <property name="productId" value="P12345"/>        <!-- 注入简单类型name是形参 -->  
        <property name="category" ref="category"/>         <!-- 注入引用类型 -->  
    </bean>  
</beans>

4. 主程序

最后,创建一个主程序,通过Spring上下文来获取Product对象并执行相应操作:

import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class Application {  
    public static void main(String[] args) {  
        // 加载Spring上下文  
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  

        // 获取product Bean  
        Product product = (Product) context.getBean("product");  
        product.displayProductInfo(); // 显示产品信息  

        // 关闭上下文  
        ((ClassPathXmlApplicationContext) context).close();  
    }  
}

运行结果

运行程序将输出以下内容:

Product ID: P12345  
Category: Electronics

二、构造器注入引用类型/简单类型(下面以同时注入这两种类型为例)

1. 定义Category

Category类保持不变,依然表示产品类别

2. 定义Product

Product类的构造函数修改为接收两个参数:一个简单类型productId和一个引用类型Category

public class Product {  
    private String productId; // 简单类型  
    private Category category; // 引用类型  

    // 构造函数注入  
    public Product(String productId, Category category) {  
        this.productId = productId;  
        this.category = category;  
    }  

    public void displayProductInfo() {  
        System.out.println("Product ID: " + productId);  
        if (category != null) {  
            category.displayInfo();  
        } else {  
            System.out.println("No category information available.");  
        }  
    }  
}

3. Spring配置文件

在Spring的XML配置文件中,使用构造器来注入简单类型和引用类型。我们可以使用constructor-arg来指定构造函数参数:

<!-- applicationContext.xml -->  
<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="category" class="com.example.Category">  
        <property name="categoryName" value="Electronics"/> <!-- 注入简单类型 -->  
    </bean>  

    <bean id="product" class="com.example.Product">  
        <constructor-arg value="P12345"/>              <!-- 注入简单类型 -->  
        <constructor-arg ref="category"/>               <!-- 注入引用类型 -->  
    </bean>  
</beans>

4. 主程序

主程序实例保持不变,只是调用已经不同的注入手段(构造器)来获取Product对象并执行操作

  • 强制依赖使用构造器进行,使用setter注入有概率不进行时导致null对象出现
  • 可选依赖使用setter注入进行,灵活性强
  • Spring框架倡导使用构造器,第三方框架内部多数采用构造器注入的形式进行数据初始化,相对严谨
  • 如果有必要可以同时使用,使用构造器注入完全依赖的注入,使用setter注入完成可选依赖的注入
  • 实际开发过程中需要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
  • 自己开发的模块推荐使用setter注入 

依赖自动装配

  • 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  • 使用按类型装配时(byType)必须保证容器中相同类型的bean唯一,推荐使用
  • 使用按名称装配时(byName)必须保证容器中具有指定名称的bean,因为变量名与配置混合,不推荐使用
  • 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

集合的注入

<!-- 定义一个bean,id为bookDao,对应的实现类为com.itheima.dao.impl.BookDaoImpl -->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <!-- 配置一个名为array的属性,类型为数组 -->
    <property name="array">
        <!-- 数组元素 -->
        <array>
            <!-- 数组中的值 -->
            <value>100</value>
            <value>200</value>
            <value>300</value>
        </array>
    </property>
    <!-- 配置一个名为list的属性,类型为列表 -->
    <property name="list">
        <!-- 列表元素 -->
        <list>
            <!-- 列表中的值 -->
            <value>itcast</value>
            <value>itheima</value>
            <value>boxuegu</value>
            <value>chuanzhihui</value>
        </list>
    </property>
    <!-- 配置一个名为set的属性,类型为集合 -->
    <property name="set">
        <!-- 集合元素 -->
        <set>
            <!-- 集合中的值,注意集合不允许重复值 -->
            <value>itcast</value>
            <value>itheima</value>
            <value>boxuegu</value>
            <!-- 重复的值boxuegu将被忽略 -->
            <value>boxuegu</value>
        </set>
    </property>
    <!-- 配置一个名为map的属性,类型为映射 -->
    <property name="map">
        <!-- 映射元素 -->
        <map>
            <!-- 映射中的键值对 -->
            <entry key="country" value="china"/>
            <!-- 可以继续添加更多的键值对 -->
        </map>
    </property>
</bean>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

源码可运行-PHP注册登录源码,PHP实现登陆后才能访问页面

最近有一个项目需要实现会员注册和页面登陆后才能访问&#xff0c;所以简单的HTML是无法实现的&#xff0c;就必须通过PHP、html和Mysql来实现&#xff0c;先给大家看一下登录和注册页的效果图。&#xff08;注册完成后会自动跳转到登录窗口&#xff0c;即使A用户登陆后分享了网…

使用Goland对6.5840项目进行go build出现异常

使用Goland对6.5840项目进行go build出现异常 Lab地址: https://pdos.csail.mit.edu/6.824/labs/lab-mr.html项目地址: git://g.csail.mit.edu/6.5840-golabs-2024 6.5840运行环境: mac系统 goland git clone git://g.csail.mit.edu/6.5840-golabs-2024 6.5840 cd 6.5840/src…

35页PDF | 元数据与数据血缘落地实施(限免下载)

一、前言 这份报告详细介绍了元数据与数据血缘的概念、重要性以及在企业数据中台中的应用。报告阐述了数据中台的核心价值在于整合和管理体系内的数据&#xff0c;以提升数据资产化能力并支持业务决策。报告还涵盖了元数据的分类&#xff08;技术元数据和业务元数据&#xff0…

【Flink】Flink Checkpoint 流程解析

Flink Checkpoint 流程解析 Checkpoint 流程解析 Flink Checkpoint 流程解析Checkpint 流程概括Checkpoint 触发流程解析 (Flink 1.20)任务启动后 JobManager 开始定期对任务执行 CheckpointJobManager 使用 CheckpointCoordinator 触发 CheckpointCheckpointCoordinator 初始化…

vue3项目最新eslint9+prettier+husky+stylelint+vscode配置

一、eslint9和prettier通用配置 安装必装插件 ESlint9.x pnpm add eslintlatest -DESlint配置 vue 规则 , typescript解析器 pnpm add eslint-plugin-vue typescript-eslint -DESlint配置 JavaScript 规则 pnpm add eslint/js -D配置所有全局变量 globals pnpm add globa…

MacOS安装软件后无法启动报错:“已损坏,无法打开,你应该将它移到废纸篓“

目录 报错截图 解决方法 知识科普 报错截图 解决方法 1. 打开系统设置->安全性与隐私->选择任何来源 2. 如果打开没有看到"任何来源"&#xff0c;如果不开启“任何来源”的选项&#xff0c;会直接影响到无法运行的第三方应用。开启“任何来源”的方法如下&a…

C++ STL 容器系列(三)list —— 编程世界的万能胶,数据结构中的百变精灵

STL系列学习参考&#xff1a; C STL系列__zwy的博客-CSDN博客https://blog.csdn.net/bite_zwy/category_12838593.html 学习C STL的三个境界&#xff0c;会用&#xff0c;明理&#xff0c;能扩展&#xff0c;STL中的所有容器都遵循这个规律&#xff0c;下面我们就按照这三个境…

Hive分区值的插入

对于Hive分区表&#xff0c;在我们插入数据的时候需要指定对应的分区值&#xff0c;而这里就会涉及很多种情况。比如静态分区插入、动态分区插入、提供的分区值和分区字段类型不一致&#xff0c;或者提供的分区值是NULL的情况&#xff0c;下面我们依次来展现下不同情况下的表现…

Python数据分析Matplotlib(一):文本说明

目录 1.1 使用matplotlib.pyplot中的title()函数设置图像标题1.2 使用matplotlib.pyplot中的annotate()函数标注文字1.3 使用matplotlib.pyplot中的text()函数设置文字说明1.4 使用matplotlib.pyplot中的legend()函数和plot中的label参数一起作用添加图例1.5 使用matplotlib.py…

AUTO TECH China 2025 华南展:探索汽车技术的新纪元

AUTO TECH China 2025 华南展&#xff1a;探索汽车技术的新纪元 随着科技的日新月异&#xff0c;汽车行业正经历着前所未有的变革。从电动化、智能化到网联化&#xff0c;每一项新技术的应用都在重塑我们对汽车的认知。为了展示这些令人激动的创新成果&#xff0c;我们荣幸地宣…

3D 生成重建017-StyleGaussian用文本或图像对你的3DGS内容进行风格迁移

3D 生成重建017-StyleGaussian用文本或图像对你的3DGS内容进行风格迁移 文章目录 0 论文工作1 论文方法2 实验结果 0 论文工作 论文 “StyleGaussian: Instant 3D Style Transfer with Gaussian Splatting” 介绍了一种新颖的3D风格迁移方法 StyleGaussian&#xff0c;该方法通…

微信小程序提交测试版,但是扫描体验版的二维码 显示 页面不存在

检查路径首页是否和我们微信小程序中的首页路径一致。 显然我的不一致。 {"pagePath": "pages/index/index","text": "产品","iconPath": "icons/Group 450.png","selectedIconPath": "/icons/组 …

[小白系列]Ubuntu安装教程-安装prometheus和Grafana

Docker安装prometheus 拉取镜像 docker pull prom/prometheus 配置文件prometheus.yml 在/data/prometheus/建立prometheus.yml配置文件。&#xff08;/data/prometheus/可根据自己需要调整&#xff09; global:scrape_interval: 15s # By default, scrape targets ev…

专业140+总分420+上海交通大学819考研经验上交电子信息与通信工程,真题,大纲,参考书。博睿泽信息通信考研论坛,信息通信考研Jenny

考研结束&#xff0c;专业819信号系统与信号处理140&#xff0c;总分420&#xff0c;终于梦圆交大&#xff0c;高考时敢都不敢想目标&#xff0c;现在已经成为现实&#xff0c;考研后劲很大&#xff0c;这一年的复习经历&#xff0c;还是历历在目&#xff0c;整理一下&#xff…

在ensp进行IS-IS网络架构配置

一、实验目的 1. 理解IS-IS协议的工作原理 2. 熟练ensp路由连接配置 二、实验要求 需求&#xff1a; 路由器可以互相ping通 实验设备&#xff1a; 路由器router6台 使用ensp搭建实验坏境&#xff0c;结构如图所示 三、实验内容 R1 u t m sys undo info en sys R1 #设…

使用 LlamaFactory 结合开源大语言模型实现文本分类:从数据集构建到 LoRA 微调与推理评估

文章目录 背景介绍文本分类数据集Lora 微调模型部署与推理期待模型的输出结果 文本分类评估代码 背景介绍 本文将一步一步地&#xff0c;介绍如何使用llamafactory框架利用开源大语言模型完成文本分类的实验&#xff0c;以 LoRA微调 qwen/Qwen2.5-7B-Instruct 为例。 文本分类…

链式设计模式

链式设计模式——装饰器模式和职责链模式 装饰模式 定义&#xff1a; 指在不改变现有对象结构的情况下&#xff0c;动态地给该对象增加一些职责&#xff08;即增加其额外功能&#xff09;的模式。 结构 装饰&#xff08;Decorator&#xff09;模式中的角色&#xff1a; 抽…

小红薯x-s算法最新补环境教程12-06更新(下)

在上一篇文章中已经讲了如何去定位x-s生成的位置&#xff0c;本篇文章就直接开始撸代码吧 如果没看过的话可以看&#xff1a;小红薯最新x-s算法分析12-06&#xff08;x-s 56&#xff09;&#xff08;上&#xff09;-CSDN博客 1、获取加密块代码 首先来到参数生成的位置&…

同三维TL200H2S2 2机位互动录播主机

2路HDMI&#xff08;1路4K30&#xff09;输入2路SDI输入4路网络摄像机输入1路USB摄像头3路互动远程网络信号解码&#xff0c;2路HDMI&#xff08;1路4K60&#xff09;输出, 音频输入&#xff1a;2路3.5mm立体声线路&#xff0c;2路凤凰头带48V幻相电源麦克风&#xff0c;音频输…

dell电脑开不了机怎么回事?戴尔电脑无法开机解决方法

dell戴尔电脑开不了机&#xff0c;这是很多使用dell电脑用户常遇到的问题。这种故障情况是由多种原因引起&#xff0c;包括硬件故障、软件问题或电源问题等等。dell电脑开不了机怎么办呢&#xff1f;下面便为大家介绍一下相关解决修复方法&#xff0c;帮助用户解决戴尔电脑无法…