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

相关推荐
cat三三14 分钟前
java之异常
java·开发语言
T___T16 分钟前
一个定时器,理清 JavaScript 里的 this
前端·javascript·面试
浙江第二深情20 分钟前
前端性能优化终极指南
java·maven
养乐多072235 分钟前
【Java】IO流
java
俊男无期36 分钟前
超效率工作法
java·前端·数据库
LYFlied36 分钟前
【每日算法】LeetCode 46. 全排列
前端·算法·leetcode·面试·职场和发展
中国胖子风清扬40 分钟前
SpringAI和 Langchain4j等 AI 框架之间的差异和开发经验
java·数据库·人工智能·spring boot·spring cloud·ai·langchain
月明长歌1 小时前
【码道初阶】牛客TSINGK110:二叉树遍历(较难)如何根据“扩展先序遍历”构建二叉树?
java·数据结构·算法
用户2190326527351 小时前
Spring Boot + Redis 注解极简教程:5分钟搞定CRUD操作
java·后端
Alice1 小时前
linux scripts
java·linux·服务器