Spring(三)对bean的详解

news2024/11/17 8:50:07

一、引入外部属性文件

首先我们将依赖进行导入:

 <!--MySQL驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <!--数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.31</version>
        </dependency>

我们所载入的bean如下所示:

  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

除此之外,我们进行查看其它标签:

        <!--initialSize:设置当前的数据库连接池中初始化为我们设置的连接个数-->
        <property name="initialSize" value="5"></property>
        <!--maxActive:当前数据库连接池里面最大能够存在的连接的数量,默认为8,获取第九个的时候,会一直处于阻塞状态-->
        <property name="maxActive" value="8"></property>
        <!--maxWait:等待Druid为我们分配连接的最大等待时间,如果不进行设置,则会一直处于阻塞状态-->
        <property name="maxWait" value="4"></property>

我们进行测试:

public class DataSourceTest {
    @Test
    public  void  testDataSource() throws SQLException {
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-datasource.xml");
        DruidDataSource dataSource = ioc.getBean(DruidDataSource.class);
        System.out.println(dataSource.getConnection());
    }
}

 我们进行测试之后如下所示:

 持此之外,IOC也可以利用读取·文件进行引入:

我们创建jdbc.properties文件,如下所示:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.username=root
jdbc.password=123456

我们在IOC里面进行引入:

<!--引入jdbc.properties,之后可以通过${key}的方式访问value-->
   <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

我们进行测试:

public class DataSourceTest {
    @Test
    public  void  testDataSource() throws SQLException {
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-datasource.xml");
        DruidDataSource dataSource = ioc.getBean(DruidDataSource.class);
        System.out.println(dataSource.getConnection());
    }
}

我们运行完之后如下所示:

二、bean的作用域:

 在Spring中可以通过配置bean标签的scope属性来指定bean的作用域范围,各取值含义如下表所示:

取值含义创建对象的时机
singleton(默认)在IOC容器中,这个bean的对象始终为单实例IOC容器初始化时
prototype这个bean在IOC容器中有多个实例获取bean时

我们载入的bean如下所示:

<bean  id="student" class="com.rgf.spring.pojo.Student">
    <property name="sid" value="1001"></property>
    <property name="sname" value="张三"></property>
</bean>

我们进行测试如下所示:

public class ScopeTest {
    @Test
    public  void  testScope(){
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-scope.xml");
        Student student1 = ioc.getBean(Student.class);
        Student student2 = ioc.getBean(Student.class);
        System.out.println(student1==student2);
    }

运行之后如下所示:

我们发现默认为单例模式。

我们利用scope进行设置:

<bean  id="student" class="com.rgf.spring.pojo.Student" scope="prototype">
    <property name="sid" value="1001"></property>
    <property name="sname" value="张三"></property>
</bean>

 我们继续进行测试,发现如下所示:

此时即不再为单例模式,而是多例模式。 

<!--scope:设置bean的作用域:
scope="singleton|prototype"
    singleton(单例):表示获取该bean所对应的对象都是同一个
    prototype(多例):表示获取该bean所对应的对象都不是同一个
    (struts2里面处理请求响应的action即为多例:struts2里面将处理请求和响应的一般叫做action,里面进行设置成员变量,比如有一个user,我们为其设置setter和getter方法,
    setter用来收集浏览器传输过来的请求参数,getter方法是把我们当前的成员变量共享在我们的请求域中,我们实现修改功能,需要把用户信息提交到我们当前的服务器里面。
    由我们当前的action里面的user请求获取,是利用set方法进行获取,会把浏览器传输过来的各个用户信息通过set方法赋值给user中的各个属性。而我们进行添加功能的时候
    ,是没有id的,我们也要把数据提交到我们的服务器中,通过user收集我们添加的这些数据,添加功能没有id的,但是现在操作的action是被spring管理的,所以我们所获取的action‘
    都是同一个,经过修改功能,我们action里面的user就已经有值了,添加功能的时候,访问的仍然是同一个action,这个时候user里面的id也是有值的。添加之后,会给我们user里面的
    各个属性进行赋值,添加页面没有id,user里面的id不会被覆盖,使用的仍然是修改功能里面的id。)
-->
    <bean  id="student" class="com.rgf.spring.pojo.Student" scope="prototype">
    <property name="sid" value="1001"></property>
    <property name="sname" value="张三"></property>
</bean>

如果在WebApplicationContext环境下还会有另外两个作用域(但不常用):

取值含义
request在一个请求范围内有效
session在一个会话范围内有效

三、bean的生命周期

具体的生命周期过程

bean对象创建(调用无参构造器)

给bean对象设置属性

bean对象初始化之前操作(由bean的后置处理器负责)

bean对象初始化(需要配置bean时指定初始化方法)

bean对象初始化之后操作(由bean的后置处理器负责)

bean对象就绪可以使用

bean对象销毁(需要配置bean时指定销毁方法)

IOC容器关闭

我们创建如下类所示:

package com.rgf.spring.pojo;

public class User {
    private  Integer id;
    private  String username;
    private  String password;
    private  Integer age;

    public User(Integer id, String username, String password, Integer age) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
    }

    public User() {
        System.out.println("生命周期1:实例化");
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        System.out.println("生命周期2:依赖注入");
        this.id = id;

    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }

    public  void  initMethod(){
        System.out.println("生命周期3:初始化");
    }

    public void  destroyMethod(){
        System.out.println("生命周期4:销毁");
    }
}

我们进行注入bean:

<?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.rgf.spring.pojo.User" init-method="initMethod" destroy-method="destroyMethod">
        <property name="id" value="1"></property>
        <property name="username" value="admin"></property>
        <property name="password" value="123456"></property>
        <property name="age" value="23"></property>
    </bean>
</beans>

测试如下所示:

package com.rgf.spring.test;

import com.rgf.spring.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifeCycleTest {
    /**
     * 1.实例化
     * 2.依赖注入
     * 3.初始化,需要通过bean的init-method属性指定初始化的方法
     * 4.IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法
     */
    @Test
    public  void  test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();

    }
}

运行之后如下所示:

 bean的后置处理器:

 bean的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到IOC容器中,需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行。

我们进行创建该方法:

package com.rgf.spring.process;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //此方法在bean的生命周期初始化之前执行
        System.out.println("MyBeanPostProcessor-->后置处理器postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // //此方法在bean的生命周期初始化之后执行
        System.out.println("MyBeanPostProcessor-->后置处理器postProcessAfterInitialization");
        return bean;
    }
}

我们进行载入bean里面:

 <bean  id="MyBeanPostProcessor" class="com.rgf.spring.process.MyBeanPostProcessor"></bean>

此时我们继续进行测试:

package com.rgf.spring.test;

import com.rgf.spring.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifeCycleTest {
    /**
     * 1.实例化
     * 2.依赖注入
     * 3.后置处理器的postProcessBeforeInitialization方法
     * 4.初始化,需要通过bean的init-method属性指定初始化的方法
     * 5.后置处理器的postProcessAfterInitialization方法
     * 6.IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法
     * 注意:
     * 若bean的作用域为单例时,生命周期的前三个步骤会在获取IOC容器时执行
     * 若bean的作用域为多例时,生命周期的前三个步骤会在获取bean时执行
     */
    @Test
    public  void  test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();

    }
}

我们运行之后如下所示:

四、bean的作用域对生命周期的影响和后置处理器

 当为单例模式的时候,我们在获取IOC的时候直接就进行了初始化:

 当我们设置为多例模式的时候:

<bean id="user" class="com.rgf.spring.pojo.User" init-method="initMethod" destroy-method="destroyMethod" scope="prototype">
        <property name="id" value="1"></property>
        <property name="username" value="admin"></property>
        <property name="password" value="123456"></property>
        <property name="age" value="23"></property>
    </bean>

我们再次执行如下所示:

 我们发现此时bean没有初始化,因为有多个对象,所以没有必要刚开始就进行bean初始化。

我们继续进行如下测试:

 @Test
    public  void  test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();

    }

运行之后如下所示:

我们发现当我们在bean里面设置为多例的时候,此时ioc没有进行销毁。此时的销毁的方法则不再由IOC容器来进行管理。 

 /**
     * 1.实例化
     * 2.依赖注入
     * 3.后置处理器的postProcessBeforeInitialization方法
     * 4.初始化,需要通过bean的init-method属性指定初始化的方法
     * 5.后置处理器的postProcessAfterInitialization方法
     * 6.IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法
     * 注意:
     * 若bean的作用域为单例时,生命周期的前三个步骤会在获取IOC容器时执行
     * 若bean的作用域为多例时,生命周期的前三个步骤会在获取bean时执行
     */

 五、FactoryBean

FactoryBean是Spring提供的一种整合第三方框架的常用机制,和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值,通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。

我们进行创建UserFactoryBean,

package com.rgf.spring.factory;

import com.rgf.spring.pojo.User;
import org.springframework.beans.factory.FactoryBean;

/**
 * FactoryBean是一个接口,需要创建一个类实现该接口
 * 其中有三个方法:
 * getObject():通过一个对象交给IOC容器管理
 * getObjectType():设置所提供对象的类型
 * isSingleton():所提供的对象是否单例
 * 当把FactoryBean的实现类配置为bean时,会将当前类中getObject()所返回的对象交给IOC容器管理。
 */
public class UserFactoryBean implements FactoryBean<User> {

    @Override
    public User getObject() throws Exception {
        return new User();
    }

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

我们进入FactoryBean,查看是否是单例:

  default boolean isSingleton() {
        return true;
    }

是单例模式

我们将bean进行载入:

<?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 class="com.rgf.spring.factory.UserFactoryBean">
  </bean>
</beans>

我们进行测试如下所示:

package com.rgf.spring.test;

import com.rgf.spring.pojo.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FactoryBeanTest {
    @Test
    public  void  testFactoryBean(){
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-factory.xml");
        User u = ioc.getBean(User.class);
        System.out.println(u);
    }
}

运行之后如下所示: 

我们在bean里面没有进行配置该对象,但是最后却获取到了。  

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

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

相关文章

idea连接Linux服务器

一、 介绍 配置idea的ssh会话和sftp可以实现对linux远程服务器的访问和文件上传下载&#xff0c;是替代Xshell的理想方式。这样我们就能在idea里面编写文件并轻松的将文件上传到linux服务器中。而且还能远程编辑linux服务器上的文件。掌握并熟练使用&#xff0c;能够大大提高我…

烂怂if-else代码优化方案 | 京东云技术团队

0.问题概述 代码可读性是衡量代码质量的重要标准&#xff0c;可读性也是可维护性、可扩展性的保证&#xff0c;因为代码是连接程序员和机器的中间桥梁&#xff0c;要对双边友好。Quora 上有一个帖子&#xff1a; “What are some of the most basic things every programmer s…

日本医疗保健和健康管理公司【Zerospo】申请纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;来自日本的医疗保健和健康管理公司【Zerospo】&#xff0c;近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票代码为&#xff…

感谢海洋一所陈老师用Pospac MMS解算pospac数据及GNSS验潮

非常感谢海洋一所陈老师 帮忙用Pospac MMS解算博主的pospa从数据。解算的结果txt文件大小有2个G&#xff0c;令人非常吃惊&#xff0c;因为原始数据的时长不到1天&#xff0c;打开文件才知道每行位置数据的间隔时间是5ms&#xff0c;5ms正是惯导数据的采样频率。 用抽稀软件按…

短视频矩阵系统源码-开源开发php语言搭建

短视频矩阵系统源码---------- php源码是什么&#xff1f; PHP源码指的就是PHP源代码&#xff0c;源代码是用特定编程语言编写的人类可读文本&#xff0c;源代码的目标是为可以转换为机器语言的计算机设置准确的规则和规范。因此&#xff0c;源代码是程序和网站的基础。 PHP…

【数据结构】插入排序详细图解(一看就懂)

&#x1f4af; 博客内容&#xff1a;【数据结构】插入排序详细图解&#xff08;一看就懂&#xff09; &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f989;所属专栏&#xff1a;数据结构笔记 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准前端&#xff0c;…

ARM-FS6818-点亮LED灯

点亮LED灯 1.开发板介绍 2.cpu控制硬件原理 六大指令里边&#xff0c;只有内存访问指令能访问cpu之外的内容。那cpu如何控制硬件&#xff1f; *load/store指令-->操作4G内存 任何一个芯片都有一个地址映射表。告诉地址空间是如何映射的&#xff0c;便于我们找到对应的硬件地…

ChatGPT3.5-4资源汇总,直连无梯子

什么是ChatGPT? ChatGPT&#xff0c;全称&#xff1a;聊天生成预训练转换器&#xff08;英语&#xff1a;Chat Generative Pre-trained Transformer&#xff09;&#xff0c;是OpenAI开发的人工智能聊天机器人程序&#xff0c;于2022年11月推出。该程序使用基于GPT-3.5、GPT-4…

limou的C语言学习路径

0.前言 你好这里是limou3434的一篇个人博文&#xff0c;感兴趣的话您可以到我的CSDN博客上看看&#xff0c;下面我将以前学习了大概7个月的C语言学习总结给您做一个集合&#xff0c;希望能够帮助到您。 1.C语言大略 学习C前的一些基础知识 这篇文章简单过一下C语言的基础&a…

U盘移动硬盘变本地硬盘怎么办 ,移动硬盘变本地硬盘的恢复方法

这是分区逻辑损坏后最常见的表现。U盘移动硬盘变本地硬盘怎么办 &#xff0c;移动硬盘变本地硬盘的恢复方法有些用人到这种情况后首先会尝试使用Windows系统自带的硬盘修复工具chk命令进行修复&#xff0c;不过&#xff0c;这样操作并不能解决问题&#xff0c;往往会造成更严重…

UFS 2 -UFS架构简介2

UFS 2 -UFS架构简介2 1 UFS架构简介1.1 System Boot and Enumeration1.2 UFS Interconnect (UIC) Layer1.2.1 UFS Physical Layer Signals1.2.2 MIPI UniPro1.2.3 MIPI UniPro Related Attributes 1.3 UFS Transport Protocol (UTP) Layer1.3.1 Architectural Model1.3.1.1 Cli…

ChatGPT时代:数据标注会成为一种人机交互“语言”么?

标注猿的第70篇原创 一个用数据视角看AI世界的标注猿 大家好&#xff0c;我是AI数据标注猿刘吉&#xff0c;一个用数据视角看AI世界的标注猿。 从去年的10月份到现在有半年的时间没有更新了&#xff0c;去年没有更新是疫情的原因&#xff0c;今年没有更新主要有两个原因一…

微软联合OpenAI发大招了,上线Windows Copilot,速来围观~

目录 前言 Windows Copilot 问世 Bing Chat 插件功能上线 Edge 与 365 Copilot 结合 搭建你的第一个AI应用&#xff08;Azure AI Studio&#xff09; 总结 写到最后 大家好&#xff0c;我是大侠&#xff0c;AI领域的专业博主 前言 ChatGPT如今已成为炙手可热的话题&am…

面向亚裔人群的美国华人超市【Maison Solutions】申请纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;来自美国南加州的面向亚裔人群的美国华人超市【美生科技Maison Solutions】近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票…

软考A计划-试题模拟含答案解析-卷十四

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

ipad触控笔是哪几款?一般电容笔和Apple pencil区别

和苹果Pencil最大的区别就是&#xff0c;电容笔没具备重力压感&#xff0c;只有一种倾斜的压感。如果你不经常画画&#xff0c;那么你可以使用一款平替电容笔。这种平替电容笔&#xff0c;不仅仅是用在办公上&#xff0c;还能用来做笔记和练习。更何况&#xff0c;现在苹果一款…

2023苹果电脑专用下载工具Folx5.27.13991

Mac 上免费的网络下载管理器 Folx Mac 下载器有一个支持 Retina 显示的现代界面。提供独特的系统排序、存储下载内容与预览下载文件。Folx 的 PRO 版是优秀的 BT 查找工具 - 您无需在网络浏览器中打开多个种子追踪器来查找您需要的内容。 虽然苹果系统比较封闭&#xff0c;如果…

蔚来Java实习面经

目录 1.解释一下MySQL中脏读、不可重复读、幻读2.索引失效的场景有哪些&#xff1f;3.Explain执行计划用过吗4.Type字段有哪一些5.binlog和redolog的区别6.Redis基本数据类型7.有序集合的底层数据结构使用的是&#xff1f;8.跳表插入数据的过程能描述一下吗9.线程池&#xff0c…

两个直线/线段的交点 - golang

问题&#xff0c;求上图中线段AB 和线段CD的交点P的坐标 根据《算法艺术与信息学竞赛》&#xff0c;公式如下 原理&#xff1a; 利用叉积求得点P分线段DC的比&#xff0c;然后利用高中学习的定比分点坐标公式求得分点P的坐标 要注意的是 若判断是两条线段&#xff0c;需先判…

GPT到底有多聪明?附上一份GPT研究报告!(十七)

转载自 AI 源起 GPT的出现&#xff0c;不得不说是人类整个科技发展史上的里程碑。那么你知道GPT到底有多聪明吗&#xff1f;它的边界在哪&#xff1f;我们这个系列将为您着重阐述这一点。 人的专长、工作和经济 GPT-4在一系列任务和领域中的卓越表现将挑战关于人类和机器在…