SpringBean的生命周期

SpringBean的生命周期

  • SperingBean的生命周期是从Bean实例化之后,即通过反射创建出对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为Spring Bean的生命周期。Spring Bean的生命周期大体上分为三个阶段
    • Bean的实例化阶段:Spring框架会取出BeanDefiniton的信息进行判断当前Bean的范围是否是singleton的,是否不是延迟加载的,是否不是FactoryBean等,最终将一个普通的singleton的Bean通过反射(加载类)进行实例化
    • Bean的初始化阶段(着重研究):Bean创建之后还仅仅是个半成品,还需要对Bean实例的属性进行填充、执行一些Aware接口方法、执行BeanPostProcessor方法,执行InitializingBean接口的初始化方法、执行自定义初始化init方法等。该阶段是Spring最具有技术含量和复杂程度的阶段,AOP增强功能,后面学习的Spring的注解功能等、spring高频面试题Bean的循环引用问题都是在这个阶段体现的
    • Bean的完成阶段:经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池singletonObjects中,即完成了Spring Bean的整个生命周期。

Spring Bean的初始化阶段涉及过程

  • Bean实例属性的填充
  • Aware接口属性的注入
  • BeanPostProcessor的before()方法回调
  • InitializingBean接口的初始化方法回调
  • 自定义初始化方法init回调
  • BeanPostProcessor的after()方法回调

Bean实例属性填充

  • BeanDefinition中对当前Bean实体的注入信息通过属性propertyValue进行了储存,例如UserService的属性信息如下

    XML 复制代码
        <bean id="userService" class="com.example.Service.Impl.UserServiceImpl">
            <property name="userDAO" ref="userDAO"></property>
            <property name="name" value="hhhh"></property>
        </bean>
        <bean name="userDAO" class="com.example.DAO.Impl.UserDAOImpl"></bean>

属性注入的三种情况

  • 注入普通属性,String,int或存储基本类型的集合时,直接通过set方法反射设置进去

    • 上述属性name对应类中的set方法
  • 注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没有,则先创建被注入对象Bean实例(完成整个生命周期)后,再进行注入操作

    • 上述UserDAO属性的注入
    • 根据配置文件中bean的位置不同,进行的顺序也不一样
    • 主要代码如下
    • UserServiceImpl类
    java 复制代码
    package com.example.Service.Impl;
    
    import com.example.DAO.UserDAO;
    import com.example.Service.UserService;
    
    
    public class UserServiceImpl implements UserService {
        public UserServiceImpl() {
            System.out.println("UserService对象创建");
        }
    
        private UserDAO userDAO;
        private String name;
    
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setUserDAO(UserDAO userDAO) {
            System.out.println("UserService执行注入UserDAO的操作:setDAO方法");
            this.userDAO = userDAO;
        }
    
        @Override
        public void show() {
            System.out.println("show~~~");
        }
    }
    • UserDAOImpl类

    java 复制代码
    package com.example.DAO.Impl;
    
    import com.example.DAO.UserDAO;
    
    public class UserDAOImpl implements UserDAO {
    
        public UserDAOImpl() {
            System.out.println("UserDAO对象创建");
        }
    }
    • 测试类

    java 复制代码
    package com.example.Test;
    
    
    import com.example.Service.UserService;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestApplicationContext {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
            UserService UserServiceBean = (UserService) context.getBean(UserService.class);
        }
    }
    • 若配置文件中先创建UserADO的bean对象

    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">
        <bean class="com.example.PostProcessor.TimeLogBeanPostProcessor"></bean>
        <!--    <bean id="userService" class="com.example.Service.Impl.UserServiceImpl">-->
        <!--    </bean>-->
        <!--    <bean id="userDAO" class="com.example.DAO.Impl.UserDAOImpl">-->
        <!--    </bean>-->
        <!--    <alias name="userDAO" alias="xxx"/>-->
        <!--    <alias name="userDAO" alias="yyy"/>-->
        <bean name="userDAO" class="com.example.DAO.Impl.UserDAOImpl"></bean>
        <bean id="userService" class="com.example.Service.Impl.UserServiceImpl">
            <property name="userDAO" ref="userDAO"></property>
            <property name="name" value="hhhh"></property>
        </bean>
    
    </beans>
    • 测试类运行结果为

    • 若配置文件中先创建UserService的bean对象

    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">
        <bean class="com.example.PostProcessor.TimeLogBeanPostProcessor"></bean>
        <!--    <bean id="userService" class="com.example.Service.Impl.UserServiceImpl">-->
        <!--    </bean>-->
        <!--    <bean id="userDAO" class="com.example.DAO.Impl.UserDAOImpl">-->
        <!--    </bean>-->
        <!--    <alias name="userDAO" alias="xxx"/>-->
        <!--    <alias name="userDAO" alias="yyy"/>-->
    
        <bean id="userService" class="com.example.Service.Impl.UserServiceImpl">
            <property name="userDAO" ref="userDAO"></property>
            <property name="name" value="hhhh"></property>
        </bean>
        <bean name="userDAO" class="com.example.DAO.Impl.UserDAOImpl"></bean>
    
    </beans>
    • 运行结果如下

  • 注入双向对象引用属性时,就比较复杂了,涉及循环引用(循环依赖)问题,下面会详细阐释解决方案。(明天再来,女朋友来了,不能学习了p51

相关推荐
加载中36129 分钟前
pnpm时代包版本不一致问题还是否存在
前端·面试·npm
爱吃苹果的日记本32 分钟前
开学第一课
java
学历真的很重要1 小时前
Claude Code Windows 原生版安装指南
人工智能·windows·后端·语言模型·面试·go
渣哥1 小时前
Java 集合框架详解:常见集合类及分类方式
java
yinke小琪1 小时前
消息队列如何保证消息顺序性?从原理到代码手把手教你
java·后端·面试
考虑考虑1 小时前
Java实现墨水屏点阵图
java·后端·java ee
_extraordinary_2 小时前
Java 多线程(一)
java·开发语言
网安Ruler2 小时前
第49天:Web开发-JavaEE应用&SpringBoot栈&模版注入&Thymeleaf&Freemarker&Velocity
java·spring boot·后端
FLS1682 小时前
Kali搭建sqli-labs靶场
linux·sql·安全·网络安全
奔跑吧邓邓子2 小时前
【Java实战㉟】Spring Boot与MyBatis:数据库交互的进阶之旅
java·spring boot·实战·mybatis·数据库交互