当前位置: 首页 > news >正文

Spring Bean的生命周期

BeanFactory 与 ApplicationContext 的区别

  1. 到底什么是 BeanFactory

    • 它是 ApplicationContext 的父接口

    • 它才是 Spring 的核心容器, 主要的 ApplicationContext 实现都【组合】了它的功能,【组合】是指 ApplicationContext 的一个重要成员变量就是 BeanFactory

  1. BeanFactory 能干点啥

    • 表面上只有 getBean

    • 实际上控制反转、基本的依赖注入、直至 Bean 的生命周期的各种功能,都由它的实现类提供

    • 例子中通过反射查看了它的成员变量 singletonObjects,内部包含了所有的单例 bean

  1. ApplicationContext 比 BeanFactory 多点啥

    • ApplicationContext 组合并扩展了 BeanFactory 的功能

    • 国际化、通配符方式获取一组 Resource 资源、整合 Environment 环境、事件发布与监听

    • 事件解耦(org.springframework.context.ApplicationEventPublisher#publishEvent(java.lang.Object) 、org.springframework.context.event.EventListener)

2) 容器实现

  • DefaultListableBeanFactory,是 BeanFactory 最重要的实现,像控制反转依赖注入功能,都是它来实现

  • ClassPathXmlApplicationContext,从类路径查找 XML 配置文件,创建容器(旧)

  • FileSystemXmlApplicationContext,从磁盘路径查找 XML 配置文件,创建容器(旧)

  • XmlWebApplicationContext,传统 SSM 整合时,基于 XML 配置文件的容器(旧)

  • AnnotationConfigWebApplicationContext,传统 SSM 整合时,基于 java 配置类的容器(旧)

  • AnnotationConfigApplicationContext,Spring boot 中非 web 环境容器(新)

  • AnnotationConfigServletWebServerApplicationContext,Spring boot 中 servlet web 环境容器(新)

  • AnnotationConfigReactiveWebServerApplicationContext,Spring boot 中 reactive web 环境容器(新)

另外要注意的是,后面这些带有 ApplicationContext 的类都是 ApplicationContext 接口的实现,但它们是组合DefaultListableBeanFactory 的功能,并非继承而来。

  • beanFactory 可以通过 registerBeanDefinition 注册一个 bean definition 对象

    • 我们平时使用的配置类、xml、组件扫描等方式都是生成 bean definition 对象注册到 beanFactory 当中

    • bean definition 描述了这个 bean 的创建蓝图:scope 是什么、用构造还是工厂创建、初始化销毁方法是什么,等等

    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 的定义(class, scope, 初始化, 销毁)
        // My: 使用建造者模式 生成bean的定义( bean 类名) 设置作用域 单例。 建造
        AbstractBeanDefinition beanDefinition =
                                        BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        // My:在beanFactory添加(注册Bean定义)一个Bean
        beanFactory.registerBeanDefinition("config", beanDefinition);
  • beanFactory 需要手动调用 beanFactory 后处理器对它做增强

    • 例如通过解析 @Bean、@ComponentScan 等注解,来补充一些 bean definition

  • beanFactory 需要手动添加 bean 后处理器,以便对后续 bean 的创建过程提供增强

    • 例如 @Autowired,@Resource 等注解的解析都是 bean 后处理器完成的

    • bean 后处理的添加顺序会对解析结果有影响,见视频中同时加 @Autowired,@Resource 的例子

  • beanFactory 需要手动调用方法来初始化单例

  • beanFactory 需要额外设置才能解析 ${} 与 #{}

3) Bean 的生命周期

BeanFactory 文档注释未提及 InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor -> 
BeanPostProcessor -> DestructionAwareBeanPostProcessor

创建前后的增强

  • postProcessBeforeInstantiation

    • 这里返回的对象若不为 null 会替换掉原本的 bean,并且仅会走 postProcessAfterInitialization 流程

  • postProcessAfterInstantiation

    • 这里如果返回 false 会跳过依赖注入阶段

依赖注入前的增强

  • postProcessProperties

    • 如 @Autowired、@Value、@Resource

初始化前后的增强

  • postProcessBeforeInitialization

    • 这里返回的对象会替换掉原本的 bean

    • 如 @PostConstruct、@ConfigurationProperties

  • postProcessAfterInitialization

    • 这里返回的对象会替换掉原本的 bean

    • 如代理增强

销毁之前的增强

  • postProcessBeforeDestruction

    • 如 @PreDestroy

 

演示2 - 模板方法设计模式

 Bean的生命周期 第14 步可添加多个 BeanPostProcessor 在这里拓展一种模板方法设计模式

import java.util.function.BiFunction;

/**
 * 自定义的函数对象 参照了 org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
 * @author Jay
 */
public class MyBeanPostProcessor {
    /**
     * Bean 后处理器
      */
    private BiFunction function;

    /**
     * T,参数一
     */
    private Object bean;

    /**
     * U, 参数二
     */
    private String beanName;

    /**
     * R, BiFunction 的返回值
     */
    private Object returnValue;

    /**
     * 需要全部的参数才能实例化
     * @param bean
     * @param beanName
     * @param function
     */
    public MyBeanPostProcessor(Object bean, String beanName, BiFunction function) {
        this.bean = bean;
        this.beanName = beanName;
        this.function = function;
    }

    public BiFunction getFunction() {
        return function;
    }

    public void setFunction(BiFunction function) {
        this.function = function;
    }

    public Object getBean() {
        return bean;
    }

    public void setBean(Object bean) {
        this.bean = bean;
    }
import java.util.ArrayList;
import java.util.List;

public abstract class Game {

    private List<MyBeanPostProcessor> processors = new ArrayList<>();

    /**
     * 初始化游戏
     */
    abstract void initialize();

    /**
     * 开始游戏
     */
    abstract void startPlay();

    /**
     * 结束游戏
     */
    abstract void endPlay();

    public void addFunction(MyBeanPostProcessor function) {
        processors.add(function);
    }

    /**
     * 模板方法 不可重写
     */
    public final void play() {

        initialize();

        startPlay();
        // 依次执行 MyBeanPostProcessor 的 getReturnValue
        for (MyBeanPostProcessor processor : processors) {
//            processor.getFunction().apply(processor.getBean(), processor.getBeanName());
            processor.getReturnValue();
        }
        
        endPlay();
    }
}
public class FootBall extends Game{
    @Override
    void initialize() {
        System.out.println("FootBall Game initializing...");
    }

    @Override
    void startPlay() {
        System.out.println("FootBall Game  startPlay");
    }

    @Override
    void endPlay() {
        System.out.println("FootBall Game is end");
    }
}
public class Cricket extends Game{
    @Override
    public final void initialize() {
        System.out.println("Cricket Game initialize");
    }

    @Override
    public final void startPlay() {
        System.out.println("Cricket Game startPlay");
    }

    @Override
    public final void endPlay() {
        System.out.println("Cricket Game endPlay");
    }
}
/**
 * @author Jay
 */
public class TemplatePatternDemo {
    public static void main(String[] args) {
        Game footBall = new FootBall();
        // 添加 BeanPostProcessor
        footBall.addFunction(
                new MyBeanPostProcessor("1", "1", (bean, beanName) -> {
                    System.out.println("解析 @Bean");
                    return bean;
                })
        );
        footBall.addFunction(
                new MyBeanPostProcessor("1", "1", (bean, beanName) -> {
                    System.out.println("解析 @Resource");
                    return bean;
                })
        );

        footBall.addFunction(
                new MyBeanPostProcessor("1", "1", (bean, beanName) -> {
                    System.out.println("解析 @Autowired");
                    return bean;
                })
        );

        footBall.play();
        

        Game cricket = new Cricket();
        cricket.play();
    }
}

bean(后处理器)排序

收获💡

  1. 实现了 PriorityOrdered 接口的优先级最高

  2. 实现了 Ordered 接口与加了 @Order 注解的平级, 按数字升序

  3. 其它的排在最后

PostProcessorRegistrationDelegate[ AbstractApplicationContext的后处理器处理的委托]

 注册与调用 BeanFactoryPostProcessor bean

 Bean后处理器的注册与使用

注册 :org.springframework.beans.factory.config.ConfigurableBeanFactory#addBeanPostProcessor

 调用:org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(java.util.Collection<? extends org.springframework.beans.factory.config.BeanFactoryPostProcessor>, org.springframework.beans.factory.config.ConfigurableListableBeanFactory)

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;

import javax.annotation.Resource;

public class TestBeanFactory {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 的定义(class, scope, 初始化, 销毁)
        // My: 使用建造者模式 生成bean的定义( bean 类名) 设置作用域 单例。 建造
        AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        // My:在beanFactory添加(注册Bean定义)一个Bean
        beanFactory.registerBeanDefinition("config", beanDefinition);

        // 给 BeanFactory 添加一些常用的后处理器
        // My:在给定的注册表中注册所有相关的注释后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        // BeanFactory 后处理器主要功能,补充了一些 bean 定义
        // 通过Bean的类型获取(后处理器)PostProcessor
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            // 执行BeanFactory后处理器
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });


        // Bean 后处理器, 针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource ...
        // 先加入的 Bean后处理器的优先级更高一点。 所以 @Autowired 高于 @Resource 但是顺序也是可以控制的
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
                .sorted(beanFactory.getDependencyComparator())
                .forEach(beanPostProcessor -> {
            System.out.println(">>>>" + beanPostProcessor);
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        });

        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }
    }
    interface Inter {

    }

    static class Bean3 implements Inter {

    }

    static class Bean4 implements Inter {

    }

    static class Bean1 {
        private static final Logger log = LoggerFactory.getLogger(Bean1.class);

        public Bean1() {
            log.debug("构造 Bean1()");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }

        @Autowired
        @Resource(name = "bean4") // resource 比Autowired 找的就高级一些了
        // 当我使用接口时候 使用的是成员变量的名字 inter去找 就可能找不到了
        // 两个同时存在的话  因为BeanPostProcessor相关的后处理器的默认顺序AutowiredAnnotation比CommonAnnotation 优先级高所以 AutoWired高
        // 可通过 sorted 的 dependencyComparator控制顺序
        private Inter bean3;

        public Inter getInter() {
            return bean3;
        }
    }

    static class Bean2 {
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);

        public Bean2() {
            log.debug("构造 Bean2()");
        }
    }
}

4) Bean 后处理器

        自定义修改新bean实例

演示1 - 后处理器作用

代码参考

com.itheima.a04

收获💡

  1. @Autowired 等注解的解析属于 bean 生命周期阶段(依赖注入, 初始化)的扩展功能,这些扩展功能由 bean 后处理器来完成

  2. 每个后处理器各自增强什么功能

    • AutowiredAnnotationBeanPostProcessor 解析 @Autowired 与 @Value

    • CommonAnnotationBeanPostProcessor 解析 @Resource、@PostConstruct、@PreDestroy

    • ConfigurationPropertiesBindingPostProcessor 解析 @ConfigurationProperties

  3. 另外 ContextAnnotationAutowireCandidateResolver 负责获取 @Value 的值,解析 @Qualifier、泛型、@Lazy 等

 

演示2 - @Autowired bean 后处理器运行分析

代码参考

com.itheima.a04.DigInAutowired

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

// AutowiredAnnotationBeanPostProcessor 运行分析
public class DigInAutowired {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2()); // 创建过程,依赖注入,初始化
        beanFactory.registerSingleton("bean3", new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); // @Value
        // 添加字符串解析器
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // ${} 的解析器

        // 1. 查找哪些属性、方法加了 @Autowired, 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println(bean1);
        processor.postProcessProperties(null, bean1, "bean1"); // 执行依赖注入 @Autowired @Value
        System.out.println(bean1);

        // processor.postProcessProperties 所做的工作: 1\查找注解 @Autowired @Value findAutowiringMetadata() 2\执行注入 metadata.inject()
        // 解析{} 需要使用EmbeddedValueResolver
        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class
                .getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata
                .invoke(processor, "bean1", Bean1.class, null);// 获取 Bean1 上加了 @Value @Autowired 的成员变量,方法参数信息
        System.out.println(metadata);

        // 2. 调用 InjectionMetadata 来进行依赖注入, 注入时按类型查找值
        metadata.inject(bean1, "bean1", null);
        System.out.println(bean1);

        // 3. 如何按类型查找值
        Field bean3 = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor dd1 = new DependencyDescriptor(bean3, false);
        // 根据一个依述赖描(字段)获取一个对象
        Object o = beanFactory.doResolveDependency(dd1, null, null, null);
        System.out.println(o);

        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor dd2 =
                new DependencyDescriptor(new MethodParameter(setBean2, 0), true);
        Object o1 = beanFactory.doResolveDependency(dd2, null, null, null);
        System.out.println(o1);

        Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
        DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHome, 0), true);
        Object o2 = beanFactory.doResolveDependency(dd3, null, null, null);
        System.out.println(o2);

    }
}

收获💡

  1. AutowiredAnnotationBeanPostProcessor.findAutowiringMetadata 用来获取某个 bean 上加了 @Value @Autowired 的成员变量,方法参数的信息,表示为 InjectionMetadata

  2. InjectionMetadata 可以完成依赖注入

  3. InjectionMetadata 内部根据成员变量,方法参数封装为 DependencyDescriptor 类型

  4. 有了 DependencyDescriptor,就可以利用 beanFactory.doResolveDependency 方法进行基于类型的查找

 

5) BeanFactory 后处理器

        它允许自定义修改应用程序上下文的bean定义,但不能与bean实例交互。

主要实现的接口是 BeanDefinitionRegistryPostProcessor

  • ConfigurationClassPostProcessor 可以解析:@ComponentScan、@Bean、@Import、@ImportResource

  • MapperScannerConfigurer 可以解析:Mapper 接口(@MapperScan)

相关文章:

  • 秋招-致谢
  • 「实用工具—LICEcap」写博必备|动图制作|一键生成gif(GIF)
  • 3D目标检测(一)
  • 秋招面试- - -Java体系最新面试题(8)
  • 前端工程师面试题详解(四)
  • app端专项测试
  • 我操作MySQL的惊险一幕
  • 模糊预测股价走势
  • Qt之开源绘图控件QCustomPlot
  • Python 语言程序设计 第五章 字符串应用举例
  • C++ | 12天学好C++ (Day6)->结构图可视化、代码加通俗理解
  • Android Socket通讯 之 心跳消息
  • CSS高级篇——媒体查询 (Media Queries)
  • 921. 使括号有效的最少添加——Leetcode(2022.10.4)【栈模拟】
  • 前后端交互工具 ---- Ajax 的使用
  • ERLANG 网工修炼笔记 ---- UDP
  • ES6系列(二)变量的解构赋值
  • happypack两次报错的问题
  • Java编程基础24——递归练习
  • linux学习笔记
  • npx命令介绍
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • 记一次用 NodeJs 实现模拟登录的思路
  • 配置 PM2 实现代码自动发布
  • 前端技术周刊 2019-02-11 Serverless
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 手写双向链表LinkedList的几个常用功能
  • 项目实战-Api的解决方案
  • 中文输入法与React文本输入框的问题与解决方案
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​LeetCode解法汇总518. 零钱兑换 II
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #前后端分离# 头条发布系统
  • (14)Hive调优——合并小文件
  • (2015)JS ES6 必知的十个 特性
  • (C语言)fread与fwrite详解
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (poj1.3.2)1791(构造法模拟)
  • (独孤九剑)--文件系统
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (九)信息融合方式简介
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转载)Linux 多线程条件变量同步
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • @Import注解详解
  • [14]内置对象
  • [Angular] 笔记 7:模块
  • [ArcPy百科]第三节: Geometry信息中的空间参考解析
  • [BIZ] - 1.金融交易系统特点
  • [EULAR文摘] 脊柱放射学持续进展是否显著影响关节功能
  • [HDOJ4911]Inversion