spring 详解三 IOC(spring实例化及后处理器)

2023-11-01

Spring实例化基本流程

Spring在容器初始化的时候,读取XMl配置,将其封装成BeanDefinition(Bean定义)对象,描述所有bean的信息

BeanDefinition会注册存储到beanDefinitionMap集合中

Spring框架遍历beanDefinitionMap,使用反射创建Bean实例对象

创建好之后的对象存储在singletonObjects的map集合中,当getBean时,从该map中取出实例bean对象返回

Spring配置文件中的配置项都能在BeanDefinition对象中找到 

BeanDefinition是一个接口,我们使用RootBeanDefinition即可

 Spring中的两个后处理器

Spring中提供两个后处理器,让我们能够介入实例化流程,动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用

BeanFactoryPostProcessor:Bean工厂后处理器,在beanDefinitionMap填充完毕,还未反射创建对象之前执行

BeanPostProcessor:Bean后处理器 ,在Bean实例化之后,填充至singletonObjects之前执行,一但添加至singletonObjects意味着不能改变,有一个before和after,中间隔着初始化方法的执行。

一个在还未创建对象之前,一个在创建对象之后

Bean工厂后处理器 BeanFactoryPostProcessor

BeanFactoryPostProcessor是一个接口,实现了该接口的类只要交由spring容器管理的话,那么spring就会回调该接口的方法,用于对BeanDefinition注册和修改

package com.tech.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class MyBeanFactoryProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanDefinitionMap填充完毕之后执行该方法");
        // 创建一个BeanDefinition 
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClassName("com.tech.test.test.bean.DI");
        // 查看继承关系图ConfigurableListableBeanFactory就是DefaultListableBeanFactory
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
        // 注册Bean
        defaultListableBeanFactory.registerBeanDefinition("userService",rootBeanDefinition);
        
    }
}
 <bean id="userService"  name="aaa,bbb"  class="com.tech.test.service.impl.UserServiceImpl" ></bean>
<bean  class="com.tech.test.processor.MyBeanFactoryProcessor "></bean>

需要在配置文件中配置交给spring管理,这个示例 我们动态的修改对象userService为DI对象,当我们getBean时,Bean已经被修改为DI对象

spring提供了专门注册BeanDefinitionMap的接口,BeanDefinitionRegistryPostProcessor,看下继承关系,它是BeanFactoryPostProcessor 的子接口

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.beans.factory.support;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

演示相同功能 

package com.tech.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class MyNoCastProcessor implements BeanDefinitionRegistryPostProcessor {

    // 执行顺序早于postProcessBeanFactory 简记为 谁在上边谁先执行
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        // 创建一个BeanDefinition
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClassName("com.tech.test.test.bean.DI");
        // 注册Bean
        beanDefinitionRegistry.registerBeanDefinition("userService",rootBeanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}
<bean id="userService"  name="aaa,bbb"  class="com.tech.test.service.impl.UserServiceImpl" ></bean>

<bean id="process" class="com.tech.test.processor.MyNoCastProcessor"></bean>

示例:定义自定义注解实现注册对象,配置就不列举啦,需要在对象未创建之前加入Bean定义信息

自定义注解

package com.tech.test.anotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {

    String value();
}

 加上注解

package com.tech.test.testbean;


import com.tech.test.anotation.MyComponent;

@MyComponent("ceshi")
public class TestAnnotation {
}

 解析注解

package com.tech.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class ParseMyComponentProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        // 这里的全限定类名和注解中的名称应该扫描包得到,这里暂时写死
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClassName("com.tech.test.testbean.TestAnnotation");
        beanDefinitionRegistry.registerBeanDefinition("ceshi",rootBeanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

 测试注解

package com.tech.test.springtest;

import com.tech.test.testbean.DI;
import com.tech.test.testbean.TestAnnotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestParseAnnotation {

    public static void main(String[] args) {
        // 创建ApplicationContext,加载配置文件,实例化容器
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 获取Bean
        TestAnnotation testAnnotation = classPathXmlApplicationContext.getBean(TestAnnotation.class);

        System.out.println(testAnnotation);
    }
}

Bean后处理器BeanPostProcessor

Bean后处理器 ,在Bean实例化之后,填充至singletonObjects之前执行,一但添加至singletonObjects意味着不能改变

 示例:为spring中的Bean执行方法添加时间,执行开始之前加入时间,执行之后加入时间,这里使用jdk动态代理做增强

package com.tech.test.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.Proxy;
import java.util.Date;

public class MyBeanProcessor implements BeanPostProcessor {

    // before 和after之间隔着InitliazeBean初始化的执行过程

      @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        Object proxyBean = Proxy.newProxyInstance(
                bean.getClass().getClassLoader(),
                bean.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println("方法" + method.getName() + "开始时间" + new Date());

                    // 执行目标方法
                    Object invoke = method.invoke(bean, args);

                    System.out.println("方法" + method.getName() + "结束时间" + new Date());
                    return invoke;
        });
        return proxyBean;
    }
}
<bean  class="com.tech.test.processor.MyBeanProcessor"></bean>

测试结果

package com.tech.test.springtest;

import com.tech.test.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestApplicationContext {
    public static void main(String[] args) {

        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserService userService =(UserService) classPathXmlApplicationContext.getBean("userService");


        userService.getUser();

    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring 详解三 IOC(spring实例化及后处理器) 的相关文章

  • php简单登录脚本白页

    你好 我正在尝试将 PDO 植入我的登录脚本中 以使其更安全地免受 sql 注入的影响 但我得到一个白页 我认为这是因为我试图计算行数以查看用户是否是真实的 Here we inculde the function page include
  • 从 JSP 文件中的会话范围 bean 访问数据

    我正在尝试在 Spring Web MVC 3 中开始使用会话范围的 bean 我将这一行放入我的调度程序配置中
  • 对不同记录进行 PIVOT 查询

    我有下表 Id Code percentage name name1 activity 1 Prashant 43 43 James James Running 1 Prashant 70 43 Sam Sam Cooking 1 Pras
  • 错误 1364 (HY000):字段“MY_DATE”没有默认值

    create table MYTABLE MY DATE int NOT NULL AUTO INCREMENT NAME varchar 255 NOT NULL UNIQUE INSERT INTO MYTABLE NAME value
  • SQL 中最有效的搜索方式?

    我有一个包含 75 000 多行的数据库 每天添加 500 多个条目 每行都有一个标题和说明 我创建了一个 RSS 提要 它为您提供特定搜索词的最新条目 例如http site com rss rss q 披萨 http site com
  • 当在另一个表中找到匹配项时更新列

    我尝试使用表 A 中与 Passport no 匹配的值更新表 B 中的列 下面是我的sql查询 update tabel b set b country id a national id from table a a join tabel
  • 如何在 XML 配置文件中使用 Spring Boot 自动配置 bean?

    我想利用 XML 配置文件中的一些 Spring Boot 自动配置 bean 但当我尝试这样做时 我不断遇到异常和错误 例如 如果我的类路径上有与数据相关的库 Spring Boot 将自动配置一个DataSource我可以将其自动装配到
  • Grails Spring Security 插件 - 修改登录用户的权限

    我有一个简单的 Grails 应用程序 安装了 Spring Security Core 插件并且工作正常 但是 我还没有找到任何解决方案来解决在安全上下文中更新登录用户权限的问题 我不是在谈论更新当前用户的详细信息 即 springSec
  • 是否可以在 postgresql 中创建触发器而不执行过程?

    我想创建一个程序 其主体为 BL 我在 SQL 中找到了相同的示例 但在 postgresql 中没有找到 每个 RDBMS 都有自己的 SQL 语言 您无法在 PostgreSQL 中创建触发器 因为您可以在 Oracle MS SQL
  • 在 @Transactional 事务期间提交

    是否可以在标记为Spring的方法中执行提交 事务性 PersistenceContext private EntityManager em Transactional propagation Propagation REQUIRED pu
  • GRANT EXECUTE 所需的权限

    我正在为需要能够创建和删除过程但也向其他用户授予执行权限的用户创建一个组 GRANT CREATE PROCEDURE TO xxx xxx GRANT ALTER ON SCHEMA dbo TO xxx xxx 但是 我需要向组授予什么
  • SQL IN 子句比单个查询慢

    我正在使用 Hibernate 的 JPA 实现和 MySQL 5 0 67 MySQL 配置为使用 InnoDB 在执行 JPA 查询 转换为 SQL 时 我发现使用IN子句比执行单个查询慢 例子 SELECT p FROM Person
  • 为什么 @Configuration 类中的 @Autowired 字段为 null?

    这是一个例子Spring 文档 http docs spring io spring docs 4 2 8 RELEASE spring framework reference htmlsingle spring core 第 6 12 5
  • 当 SQL 包含变量时在 pgAdmin 中调试 SQL

    在 SQL Server 中 我可以从应用程序中复制 sql 代码并将其粘贴到 SSMS 中 声明并分配 sql 中存在的变量并运行 是的 很棒的调试场景 例如 请注意 我很生疏 语法可能不正确 declare x as varchar 1
  • sql查询中where子句中的CASE语句

    我正在尝试在我正在处理的查询的 where 子句中编写一个 case 语句 我正在水晶报告中导入代码 我基本上是想说明变量 类型 是否设置为 创建 以便在where子句中为该日期范围运行 否则为不同的日期范围运行 它一直给我一个错误 我似乎
  • 执行计划中是否考虑了功能?

    当查询在 SELECT 或 WHERE 子句中包含 PL SQL 函数 用户定义函数 时 如何生成执行计划 它是否也计算这些函数的成本并将其显示在执行计划中 或者这些函数只是被忽略 在此先感谢您的帮助 用户生成的函数在 SELECT 或 W
  • 如何使用 Spring Boot 注册辅助 servlet?

    我有一个额外的 servlet 需要在我的应用程序中注册 然而 使用 Spring Boot 及其 Java 配置 我不能只在web xml file 如何添加额外的 servlet 还可以使用的是ServletRegistrationBe
  • 使用绑定变量动态传递表名和列名

    有没有办法使用绑定变量将列名和表名动态传递给查询 这可以通过使用简单的串联运算符来完成 但我想要一种不同的方法来实现这一目标 EDIT OPEN abc cur FOR Select column name from table name
  • Spring Hibernate 4 支持

    我正在使用 Hibernate 4 CR1 我的应用程序之前使用 Spring hibernate 支持 版本 3 我还没有找到任何相关信息 是否有任何迹象表明 Spring 何时 或哪个版本 将提供对 Hibernate 4 的支持 UP
  • 查找缺失值

    我有一个表 有 2 个重要的列 DocEntry WebId 样本数据就像 DocEntry WebId 1 S001 2 S002 3 S003 4 S005 现在我们可以注意到 在 WebId 列中 S004 丢失了 我们如何通过查询找

随机推荐

  • Android学习路线

    Android学习路线 第一阶段 Java面向对象编程 1 Java基本数据类型与表达式 分支循环 2 String和StringBuffer的使用 正则表达式 3 面向对象的抽象 封装 继承 多态 类与对象 对象初始化和回收 构造函数 t
  • 17.网络爬虫—Scrapy入门与实战

    网络爬虫 Scrapy入门与实战 Scrapy基础 Scrapy运行流程原理 Scrapy的工作流程 Scrapy的优点 Scrapy基本使用 豆瓣网为例 创建项目 创建爬虫 配置爬虫 运行爬虫 如何用python执行cmd命令 数据解析
  • 基于R语言的贝叶斯网络模型、现代贝叶斯统计学方法

    基于R语言的贝叶斯网络模型实践技术应用 贝叶斯网络不但能够统合已有的各种统计学方法 如混合回归模型 LASSO 自回归模型 隐马模型等等 而且在很大程度上能够弥补统计学模型不能够进行因果推断的缺憾 以开源的R语言为平台 通过理论和实践相结合
  • pikachu之不安全的文件下载概述

    不安全的文件下载概述 文件下载功能在很多web系统上都会出现 一般我们当点击下载链接 便会向后台发送一个下载请求 一般这个请求会包含一个需要下载的文件名称 后台在收到请求后 会开始执行下载代码 将该文件名对应的文件response给浏览器
  • 二元对数正态分布 (bivariate lognormal distribution) 的几个性质

    二元对数正态分布 bivariate lognormal distribution 的几个性质 摘要 对数正态分布 二元正态分布 bivariate normal distribution 对数正态分布的期望与方差 二元对数正态分布的协方差
  • eclipse写MAPREDUCE程序对HBase表进行操作之 IndexBuilder(对已有表建索引)

    eclipse写MAPREDUCE程序对HBase表进行操作之 IndexBuilder 对已有表建索引 开源 hbase的example mapreduce里有个类IndexBuilder是用来对已有表建索引的 其代码有一点点需要修改 j
  • ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI

    ASP NET Process Model之一 IIS 和 ASP NET ISAPI 前几天有一个朋友在MSN上问我 ASP NET 从最初的接收到Http request到最终生成Response的整个流程到底是怎样的 我觉得这个问题涉
  • java中的CondVal_转载:do...while(0)的妙用

    MTK中有很多有关do while 0 的应用 刚开始可能有很多人不太明白为什么使用do while 0 似乎不加do while 0 该部分的代码也会只执行一次 其实do while 0 是出于优化代码考虑的 do while 0 并不是
  • C# 将ComboBox设置为禁止编辑的方法

    2018年5月8日14 53 21 将ComboBox的DropDownStyle 属性设置为 DropDownList即可 Simple 简单的下拉列表框 始终显示列表 DropDown 可以编辑 与有下拉列表 默认 DropDownLi
  • 对于随机森林的通俗理解

    原文 http blog csdn net mao xiao feng article details 52728164 对于随机森林的通俗理解 一 决策树 决策树是机器学习最基本的模型 在不考虑其他复杂情况下 我们可以用一句话来描述决策树
  • Python 量化投资实战教程(4) —KDJ 策略

    量化投资系列文章 Backtrader 教程 Python 量化投资实战教程 1 Python 量化投资实战教程 2 MACD策略 26 9 Python 量化投资实战教程 3 A股回测MACD策略 Github仓库 https githu
  • 服务治理spring cloud Admin/链路跟踪 ZipKin

    1 Spring Boot Admin Spring Boot Admin 用于监控基于 Spring Boot 的应用 它是在 Spring Boot Actuator 的基础上提供简洁的可视化 WEB UI 1 1 简介 Spring
  • linux 下 性能,Linux(ubuntu)下iostat的安装和系统性能监控

    linux系统出现了性能问题 一般我们可以通过top iostat free vmstat等命令 来查看初步定位问题 其中iostat可以给我们提供丰富的IO状态数据 iostat 由 Red Hat Enterprise Linux AS
  • IBL-镜面反射(预滤波篇)

    文章目录 1低差异序列 2重要性采样 3 GGX重要性采样 3 1 将uv坐标转化为半球向量坐标 3 2 将半球向量坐标转化为笛卡尔坐标 3 3 将切线坐标转化为世界坐标 3 4 完整代码 4 预滤波器卷积着色器 4 1 近似 4 2 获取
  • 【深入理解C++】产生临时对象的情况和解决

    文章目录 1 临时对象 2 对象作为函数的参数 以传值的方式传给函数 3 类型转换生成的临时对象 4 对象作为函数的返回值 以值的方式从函数返回 1 临时对象 临时对象 也称为匿名对象 没有变量名 没有被指针指向的对象 用完后马上调用析构
  • 使用C# ASP.NET框架构建Web应用程序

    在本文中 我们将介绍如何使用C ASP NET框架来构建功能强大的Web应用程序 ASP NET是一种用于构建Web应用程序的开发框架 而C 是一种用于编写 NET应用程序的编程语言 通过结合这两种技术 我们可以创建出稳定 可扩展和易于维护
  • 【学习day4】模型选择+过拟合和欠拟合

    主要来源 李沐老师的pytorch 动手学习深度学习 鞠躬感谢 记录每日所学 欢迎讨论 目录 一 模型选择 二 训练误差和泛化误差 三 多项式回归 1 生成数据集 2 对模型进行测试和训练 3 三阶多项式函数拟合 正态 4 线性函数拟合 欠
  • tomcat加内存限制和启动多个tomcat和设置连接数

    1 加内存限制 vim opt tomcat bin catalina sh 搜索OS 在cygwin false上加上如图那句代码 JAVA OPTS server Xms4096m Xmx4096m XX MaxPermSize 512
  • 集成学习、boosting、bagging、Adaboost、GBDT、随机森林

    集成学习算法简介 什么是集成学习 集成学习通过建立几个模型来解决单一预测问题 它的工作原理是生成多个分类器 模型 各自独立地学习和作出预测 这些预测最后结合成组合预测 因此优于任何一个单分类的做出预测 机器学习的两个核心任务 如何优化训练任
  • spring 详解三 IOC(spring实例化及后处理器)

    Spring实例化基本流程 Spring在容器初始化的时候 读取XMl配置 将其封装成BeanDefinition Bean定义 对象 描述所有bean的信息 BeanDefinition会注册存储到beanDefinitionMap集合中