3

Java开发学习(三)----Bean基础配置及其作用范围 - |旧市拾荒|

 2 years ago
source link: https://www.cnblogs.com/xiaoyh/p/16303453.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、bean基础配置

对于bean的基础配置如下

<bean id="" class=""/>

其中,bean标签的功能、使用方式以及id和class属性的作用,我们通过一张图来描述下

1126989-20220611122256691-1376858752.png

思考:

  • class属性能不能写接口如BookDao的类全名呢?

答案肯定是不行,因为接口是没办法创建对象的。

  • 前面提过为bean设置id时,id必须唯一,但是如果由于命名习惯而产生了分歧后,该如何解决?

在解决这个问题之前,我们需要准备下开发环境,内容如下:

1126989-20220611122424086-1136311503.png

二、bean的name属性

环境准备好后,接下来就可以在这个环境的基础上来学习下bean的别名配置,

首先来看下别名的配置说明:

1126989-20220611122558061-845643110.png
步骤1:配置别名

打开spring的配置文件applicationContext.xml

<?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">
​
    <!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
    <bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
    </bean>
​
    <!--scope:为bean设置作用范围,可选值为单例singloton,非单例prototype-->
    <bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>

说明:Ebi全称Enterprise Business Interface,翻译为企业业务接口

步骤2:根据名称容器中获取bean对象
public class AppForName {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //此处根据bean标签的id属性和name属性的任意一个值来获取bean对象
        BookService bookService = (BookService) ctx.getBean("service4");
        bookService.save();
    }
}
步骤3:运行程序

测试结果为:

1126989-20220611122725773-1068582993.png

注意事项:

  • bean依赖注入的ref属性指定bean,必须在容器中存在

    1126989-20220611122806493-2103332464.png
  • 如果不存在,则会报错,如下:

    1126989-20220611122830093-1214833231.png

    这个错误大家需要特别关注下:

    1126989-20220611122856709-494838985.png

    获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常NoSuchBeanDefinitionException

    遇到这样的问题通常检查名称是否写错

三、bean作用范围scope配置

关于bean的作用范围是bean属性配置的一个重点内容。看到这个作用范围,我们就得思考bean的作用范围是来控制bean哪块内容的?

我们先来看下bean作用范围的配置属性:

1126989-20220611123001558-1816304844.png

3.1 验证IOC容器中对象是否为单例

同一个bean获取两次,将对象打印到控制台,看打印出的地址值是否一致。

  • 创建一个AppForScope的类,在其main方法中来验证

    public class AppForScope {
        public static void main(String[] args) {
            ApplicationContext ctx = new 
                ClassPathXmlApplicationContext("applicationContext.xml");
    ​
            BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
            BookDao bookDao2 = (BookDao) ctx.getBean("bookDao");
            System.out.println(bookDao1);
            System.out.println(bookDao2);
        }
    }
  • 打印,观察控制台的打印结果

    1126989-20220611123044921-759425873.png
  • 结论:默认情况下,Spring创建的bean对象都是单例的

获取到结论后,问题就来了,那如果我想创建出来非单例的bean对象,该如何实现呢?

3.2 配置bean为非单例

在Spring配置文件中,配置scope属性来实现bean的非单例创建

  • 在Spring的配置文件中,修改<bean>的scope属性

    <bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope=""/>
  • 将scope设置为singleton

    <bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="singleton"/>

    运行AppForScope,打印看结果

    1126989-20220611123134198-1359291263.png
  • 将scope设置为prototype

    <bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>

    运行AppForScope,打印看结果

    1126989-20220611123148010-245031346.png
  • 结论,使用bean的scope属性可以控制bean的创建是否为单例:

    • singleton默认为单例

    • prototype为非单例

3.3 scope使用后续思考

介绍完scope属性以后,我们来思考几个问题:

  • 为什么bean默认为单例?

    • bean为单例的意思是在Spring的IOC容器中只会有该类的一个对象

    • bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高

  • bean在容器中是单例的,会不会产生线程安全问题?

    • 如果对象是有状态对象,即该对象有成员变量可以用来存储数据的,

    • 因为所有请求线程共用一个bean对象,所以会存在线程安全问题。

    • 如果对象是无状态对象,即该对象没有成员变量没有进行数据存储的,

    • 因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题。

  • 哪些bean对象适合交给容器进行管理?

    • 表现层对象 serviceImpl

    • 业务层对象 service

    • 数据层对象 dao

    • 工具对象 util

  • 哪些bean对象不适合交给容器进行管理?

    • 封装实例的域对象,因为会引发线程安全问题,所以不适合。


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK