Spring-bean相关

Spring-bean相关

一、bean配置

1.1 bean的别名配置

  • 除了id属性外,可以通过name属性给bean设置别名;

  • 可以通过id属性或name属性设置的别名来获取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">
    
        <!--  1.在pom.xml中导入spring和junit的坐标  -->
        <!--  2.配置bean(id需唯一)  -->
        <bean id="bookDao_" name="bD, bookD" class="com.sea.dao.impl.BookDaoImpl"/>
        <bean id="bookService_" name="bService bookS BSer" class="com.sea.service.impl.BookServiceImpl">
            <!--  bean标签的name属性用于给该bean起别名,多个别名之间使用逗号、分号或者空格分隔  -->
            <!--  3.配置service与dao之间的关系  -->
            <property name="bookDao" ref="bD"/>
            <!--  name: 表示配置当前Service中哪一个具体的属性  -->
            <!--  ref: 表示参照哪一个bean  -->
        </bean>
    </beans>
    
  • 多个别名之间使用逗号、分号或者空格分隔!

1.2 bean的作用范围配置

  • 通过ctx.getBean()获取的bean是否是单例对象呢?

    • 直接打印看看:
    //此处,通过getBean()获取的bean是单例对象,即多次调用返回的是同一个对象
    BookService bookService1 = (BookService)ctx.getBean("bookService_");
    BookService bookService2 = (BookService)ctx.getBean("bookService_");
    System.out.println(bookService1);
    System.out.println(bookService2);
    
    • 结果:两次获取的bean实例对象的地址一致,说明是同一个对象。

    Spring_bean的作用范围_1

  • 如何创建非单例的bean对象呢?

    • 在xml配置文件中,bean的默认scope属性为singleton,即单例模式;

    • 将该属性的值修改为prototype即可创建非单例的bean对象;

      • 如下:
      <bean id="bookService_" name="bService bookS BSer" class="com.sea.service.impl.BookServiceImpl" scope="prototype"> 
        ... 
      </bean>
      
      • 运行代码后:

      Spring_bean的作用范围_2

  • 为什么默认创建bean对象的方式为单例模式呢?

    • Spring容器中管理的bean对象实例,都是属于可复用的对象;
哪些bean对象适合交给容器进行管理呢?(单例模式)
  • 表现层对象(controller)
  • 业务层对象(service)
  • 数据层对象(mapper)
  • 工具对象(utils)
哪些bean对象不适合交给容器进行管理呢?
  • 封装实体的域对象(如domain中的实体类对象)

二、bean实例化过程

2.1 bean的创建

  • bean本质上是对象,在Java中对象通常使用构造方法进行创建

2.2 bean的三种创建方式

方式一:构造方法创建对象
  • BookDao接口
/**
 * @author: sea
 * @date: 2023/6/25 15:24
 */
public interface BookDao {
    void save();
}
  • BookDaoImpl类
/**
 * @author: sea
 * @date: 2023/6/25 15:25
 */
public class BookDaoImpl implements BookDao {

    private BookDaoImpl() {//此处私有的构造方法也可以找到【反射机制】
        System.out.println("BookDao 构造方法 被调用了!");
    }

    public void save() {
        System.out.println("Bookdao saving ... ");
    }
}
  • 配置文件
<?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="bookDao" class="com.sea.dao.impl.BookDaoImpl"/>
</beans>
  • 通过获取Spring容器创建的bean对象,并调用save方法,运行程序后控制台输出如下:

在这里插入图片描述

  • 我们发现:
    • 无论该无参构造方法是public还是private,Spring创建实例化对象时都能够访问到!【用到了反射机制,在xml配置文件中的bean标签的class属性给出了该类的完整路径】
    • 若是无参构造方法不存在,则将抛出BeanCreationException异常;
方式二:静态工厂
  • 编写静态工厂类OrderDaoFactory

    /**
     * @author: sea
     * @date: 2023/6/27 14:37
     */
    public class OrderDaoFactory {
        /**
         * 静态工厂方法:getOrderDao
         * @return OrderDao
         */
        public static OrderDao getOrderDao(){
            System.out.println("OrderDao setup ... ");
            return new OrderDaoImpl();
        }
    }
    
  • 在配置文件中配置该工厂类以及静态工厂方法

    • 1.配置bean标签的class属性值为静态工厂方法所在类的全路径;
      • 【此时,Spring容器可以创建工厂类的bean对象,但是我们需要的是静态工厂方法创建的Dao对象】
    • 2.给bean标签添加属性 factory-method,属性值为静态方法的名称
    <?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="bookDao" class="com.sea.dao.impl.BookDaoImpl"/>
    
        <!--  方式二:通过静态工厂方法创建对象  -->
        <bean id="orderDao" class="com.sea.factory.OrderDaoFactory" factory-method="getOrderDao"/>
    </beans>
    
  • 通过获取Spring容器创建的工厂类对象,调用静态工厂方法返回的相应的bean对象

    Spring_bean的创建方式_2

    • 此处可以发现:
      • 在配置文件中配置的bean都通过Spring容器创建了一个单例对象;
方式三:实例工厂
  • 编写实例工厂类

    /**
     * @author: sea
     * @date: 2023/6/27 14:37
     */
    public class UserDaoFactory {
        public UserDao getUserDao(){
            return new UserDaoImpl();
        }
    }
    
  • 配置文件中进行配置:

    • 1.配置实例工厂类bean对象

    • 2.配置相应的Dao类型的bean对象

      • 此处,通过bean标签的factory-bean属性进行配置工厂类的实例bean对象;
      • 有了工厂类的实例bean对象后,调用该对象的工厂方法创建Dao类型的bean对象;
      • 而在静态工厂中,只需要配置工厂类的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="bookDao" class="com.sea.dao.impl.BookDaoImpl"/>
    
        <!--  方式二:通过静态工厂方法创建对象  -->
        <bean id="orderDao" class="com.sea.factory.OrderDaoFactory" factory-method="getOrderDao"/>
    
        <!--  方式三:通过实例工厂方法创建对象  -->
        <bean id="userDaoFactory" class="com.sea.factory.UserDaoFactory"/>
        <bean id="userDao" factory-bean="userDaoFactory" factory-method="getUserDao"/>
    </beans>
    
  • 获取配置好的bean对象并调用对象的方法

    在这里插入图片描述

  • 存在的问题:

    • 1.配置工厂类的bean仅仅是为了配合Dao类型的bean使用,没有其他意义;
    • 2.方法名称不固定,每次都需要进行配置;
  • 解决:

方式三(改进)
  • 编写一个工厂类实现FactoryBean<T>接口,并实现接口中定义的方法;

    • Spring 容器会通过调用 getObject() 方法来获取实际的 bean 实例
    /**
     * @author: sea
     * @date: 2023/6/27 14:37
     */
    public class UserDaoFactoryBean implements FactoryBean<UserDao> {
        //实现了 FactoryBean<T> 接口并实现了接口中定义的方法后,
        // Spring 容器会通过调用 getObject() 方法来获取实际的 bean 实例。
        
        
        /**
         * 代替原始实例工厂中创建对象的方法(例如getUserDao)
         * @return
         * @throws Exception
         */
        @Override
        public UserDao getObject() throws Exception {
            return new UserDaoImpl();
        }
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
      
      	@Override
        public 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 id="userDaoFactory" class="com.sea.factory.UserDaoFactory"/>
        <bean id="userDao" factory-bean="userDaoFactory" factory-method="getUserDao"/>
    
        <!--  方式三(改进):通过FactoryBean【这是一个接口】来实例化bean对象  -->
        <bean id="userDao_fb" class="com.sea.factory.UserDaoFactoryBean"/>
    </beans>
    

三、bean的生命周期

3.1 概念

  • 生命周期:从创建到消亡的整个过程;
  • bean的生命周期:bean从创建到销毁的整体过程;
  • bean的生命周期控制:在bean创建后到销毁前的做的事情;

3.2 bean生命周期整体过程

  • 初始化容器
    • 1.创建对象(内存分配)
    • 2.执行构造方法
    • 3.执行属性注入
    • 4.执行bean初始化方法
  • 使用bean
    • 1.执行业务操作
  • 关闭/销毁容器
    • 1.执行bean销毁方法

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SEA-365

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值