Spring(三)对bean的详解

这篇具有很好参考价值的文章主要介绍了Spring(三)对bean的详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、引入外部属性文件

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

 <!--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());
    }
}

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

Spring(三)对bean的详解

 持此之外,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());
    }
}

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

Spring(三)对bean的详解

二、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);
    }

运行之后如下所示:

Spring(三)对bean的详解

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

我们利用scope进行设置:

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

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

Spring(三)对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();

    }
}

运行之后如下所示:
Spring(三)对bean的详解

 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();

    }
}

我们运行之后如下所示:

Spring(三)对bean的详解

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

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

Spring(三)对bean的详解

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

<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>

我们再次执行如下所示:

Spring(三)对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();

    }

运行之后如下所示:
Spring(三)对bean的详解

我们发现当我们在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);
    }
}

运行之后如下所示: 

Spring(三)对bean的详解

我们在bean里面没有进行配置该对象,但是最后却获取到了。  文章来源地址https://www.toymoban.com/news/detail-469865.html

到了这里,关于Spring(三)对bean的详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java启动jar包引入外部配置文件

    前提: 打出来的jar中已经包含了各个application-xxx.yml文件,jar所在位置也引入了外部的application-test.yml。 目的:运行时,希望使用的时外部 application-test.yml  文件。 使用了以下命令: 可以启动,但是,使用的时jar包里面的application-test.yml配置,而不是外部的application-test.yml文

    2024年02月12日
    浏览(43)
  • Vue 组件中如何引入外部的js文件

    在Vue中,通常我们引入一个js插件都是使用 npm  方式下载然后 import 使用的。但是我现在本地有了js文件或者是一个远程js文件链接,我不想使用 npm install xxx  的方式,有什么办法吗? 简单粗暴,直接在Vue项目的 index.html  中使用全局的方式引入,比如: 缺点: 不使用该js插

    2024年02月08日
    浏览(66)
  • Vue3:组合式函数(引入外部ts文件,修改外部ts参数)

            在 Vue 应用的概念中,“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用 有状态逻辑 的函数。更为复杂的业务逻辑可以使用store来处理         vue3中不在推荐使用mixins,在 Vue 2 中,mixins 是创建可重用组件逻辑的主要方式。尽管在 Vue 3 中保留

    2024年02月15日
    浏览(47)
  • 【Spring专题】Spring之Bean的生命周期源码解析——阶段二(二)(IOC之属性填充/依赖注入)

    由于Spring源码分析是一个前后联系比较强的过程,而且这边分析,也是按照代码顺序讲解的,所以不了解前置知识的情况下,大概率没办法看懂当前的内容。所以,特别推荐看看我前面的文章(自上而下次序): Spring底层核心原理解析【学习难度: ★★☆☆☆ 】 手写简易

    2024年02月12日
    浏览(39)
  • 73.是否可以把我们所需的Bean都放入Spring­mvc子容器里面来管理(springmvc的spring-servlet.xml中配置全局扫描)?

    可以 , 因为父容器的体现无非是为了获取子容器不包含的bean, 如果全部包含在子容器完全用不到父容器了, 所以是可以全部放在springmvc子容器来管理的。 虽然可以这么做不过一般应该是不推荐这么去做的,一般人也不会这么干的。如果你的项目里有用到事物、或者aop记得也

    2024年02月21日
    浏览(46)
  • Vue 组件中如何引入外部的js文件 的10种方法

    在Vue组件的 script 标签中使用 import 语句引入外部的JavaScript文件,适用于单个组件需要使用外部JavaScript文件的情况。这种方法可以在编译时静态地引入外部文件,并且可以通过 import 语句的路径指定具体的文件位置。 在Vue组件的 script 标签中使用 require 方法引入外部的JavaScr

    2024年02月10日
    浏览(44)
  • 【玩转Linux操作】详细讲解Shell的函数,exit,文件重定向,引入外部脚本的操作

    🎊专栏【​​​​​​​玩转Linux操作】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【Love Story】 🥰大一同学小吉,欢迎并且感谢大家指出我的问题🥰 bash 中的函数类似于C/C++中的函数,但是 return 的返回值与C/C++不同,返回的是 exit code ,取值为0~255,

    2024年02月12日
    浏览(38)
  • Spring中的bean标签详解

    用于配置对象交由Spring 来创建。 默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。 基本属性: id :Bean实例在Spring容器中的唯一标识 class :Bean的全限定名称 scope :指对象的作用范围,取值如下: 取值范围 说明 singleton 默认值,单例的 p

    2024年02月08日
    浏览(29)
  • uniapp(vue3) - 微信小程序平台使用import引入外部js文件出现undefined,正常引入js文件(sdk插件)文件路径正确但console.log控制台打印时却是undefined

    注:uniapp 小程序平台! 在使用 uniapp 微信小程序端导入 SDK 的过程中,您可能会遇到这样的情况: 使用 console.log() 打印导入的模块名称时,实际输出的名称并不是您期望的名称。这是因为 uniapp 进行了编译和打包处理后,会将代码重新命名以减小文件大小和提高执行效率,包

    2024年02月10日
    浏览(87)
  • 【Spring Boot Bean 注入详解】

    什么是 Bean 注入? 在 Spring 中,Bean 是应用程序的核心构建块。Bean 是由 Spring IoC 容器管理的对象,通过依赖注入实现对象之间的解耦。 Spring Boot 中的 Bean 注入 在 Spring Boot 中,Bean 注入通常通过 @Autowired 、 @Component 、 @Service 、 @Repository 等注解实现。 @Autowired 用于自动装配

    2024年02月21日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包