BeanFactory与ApplicationContext基本介绍

news2024/11/17 15:56:38

接口定义能力,抽象类实现接口的一些重要方法,最后实现类可以实现自己的一些逻辑

BeanFactory简介

仅仅是一个接口,Spring 的核心容器,并不是IOC容器的具体实现,它的一些具体实现类才是

BeanFactory 与 ApplicationContext 的区别

  • BeanFactory 是 ApplicationContext 的父接口
  • BeanFactory才是 Spring 的核心容器, 主要的 ApplicationContext 实现和【组合】了它的功能

image-20230709003040397

BeanFactory的作用

image-20230709000235024

  • 表面上只有 getBean(通过名称或者类型)
  • 实际上控制反转、基本的依赖注入、直至 Bean 的生命周期的各种功能, 都由它的实现类提供

SpringBoot启动方法返回对象就是BeanFactory实现类之一ConfigurableApplicationContext

image-20230709003144875

@SpringBootApplication
public class SpringDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);
        System.out.println(context);
    }
}

DefaultListableBeanFactory是一个比较重要的实现类

image-20230708225041588

使用反射,通过其一个父类DefaultSingletonBeanRegistry获得spring容器中以component名称开头的Bean对象:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    // beanName -> 单例对象
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
    // ...
}
        ConfigurableApplicationContext context = SpringApplication.run(SpringDemoApplication.class, args);
        Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        // 私有属性设置可访问
        singletonObjects.setAccessible(true);
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		// 通过反射获得类中属性
        Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
        map.entrySet().stream().filter(e -> e.getKey().startsWith("component"))
                .forEach(e -> {
                    System.out.println(e.getKey() + "=" + e.getValue());
                });

ApplicationContext的主要功能

四大功能

来源于四个父接口

image-20230709015433475

MessageSource-国际化资源

准备不同国际语言配置文件:

image-20230709004645884

打印不同配置文件的内容:

        System.out.println(context.getMessage("hi", null, Locale.CHINA));
        System.out.println(context.getMessage("hi", null, Locale.ENGLISH));
        System.out.println(context.getMessage("hi", null, Locale.JAPANESE));

ResourcePatternResolver-通配符匹配资源

获取指定路径下的资源:

        Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
        for (Resource resource : resources) {
            System.out.println(resource);
        }

EnvironmentCapable-处理环境信息

打印配置信息:

        // java配置信息
		System.out.println(context.getEnvironment().getProperty("java_home"));
		// yml配置信息
        System.out.println(context.getEnvironment().getProperty("server.port"));

ApplicationEventPublisher-发布事件对象【事件解耦】

首先:定义不同事件对象

public class UserRegisteredEvent extends ApplicationEvent {
    public UserRegisteredEvent(Object source) {
        super(source);
    }
}

其次:发布者发布事件

@Component
public class Component1 {

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

    @Autowired
    private ApplicationEventPublisher publisher;

    public void register() {
        log.debug("用户注册");
        // source:发布者
        publisher.publishEvent(new UserRegisteredEvent(this));
    }

}

最后:不同对象处理事件

@Component
public class Component2 {

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

    // 注解,监听事件对象
    @EventListener
    public void sendMsg(UserRegisteredEvent event) {
        log.debug("{}", event);
        log.debug("发送短信");
    }
}

BeanFactory常见实现类

image-20230709011539214

DefaultListableBeanFactory

DefaultListableBeanFactory只是一个空的容器,需要往容器里注册一些bean,默认没有一些后置处理器,要想具备这些功能,需要手动添加后置处理器并且执行

public class TestBeanFactory {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 的定义(class, scope, 初始化, 销毁)
        AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config", beanDefinition);

        // 给 BeanFactory 添加一些常用的后处理器 同时也会设置比较器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        // BeanFactory 后处理器主要功能,补充了一些 bean 定义
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        // Bean 后处理器, 针对 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);
        }

        // 准备好所有单例	
        beanFactory.preInstantiateSingletons(); 
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ");
//        默认延迟创建bean对象
//        System.out.println(beanFactory.getBean(Bean1.class).getBean2());
        System.out.println(beanFactory.getBean(Bean1.class).getInter());

        System.out.println("Common:" + (Ordered.LOWEST_PRECEDENCE - 3));
        System.out.println("Autowired:" + (Ordered.LOWEST_PRECEDENCE - 2));
    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }

        @Bean
        public Bean3 bean3() {
            return new Bean3();
        }

        @Bean
        public Bean4 bean4() {
            return new Bean4();
        }
    }

    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")
        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()");
        }
    }
}

image-20230709010752587

image-20230709010939901

小结

  • beanFactory 不会做的事

  • 不会主动添加、调用 BeanFactory 后置处理器

  • 不会主动添加 Bean 后置处理器

  • 不会主动初始化单例

  • 不会解析beanFactory 还不会解析 ${ } 与 #{ }

  • bean 后处理器会有排序的逻辑 根据order排序

ApplicationContext常见实现类

image-20230709013020574

ApplicationContext相当于会自动给BeanFactory容器后置处理器,操作更加方便一点

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

    public static void main(String[] args) {
        testClassPathXmlApplicationContext();
//        testFileSystemXmlApplicationContext();
//        testAnnotationConfigApplicationContext();
//        testAnnotationConfigServletWebServerApplicationContext();

        /*
            学到了什么
                a. 常见的 ApplicationContext 容器实现
                b. 内嵌容器、DispatcherServlet 的创建方法、作用
         */
    }

    // 较为经典的容器, 基于 classpath 下 xml 格式的配置文件来创建
    private static void testClassPathXmlApplicationContext() {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-beans.xml");

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        System.out.println(context.getBean(Bean2.class).getBean1());
    }

    // 基于磁盘路径下 xml 格式的配置文件来创建
    private static void testFileSystemXmlApplicationContext() {
        FileSystemXmlApplicationContext context =
                new FileSystemXmlApplicationContext(
                        "src\\main\\resources\\spring-beans.xml");
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        System.out.println(context.getBean(Bean2.class).getBean1());
    }

    // 较为经典的容器, 基于 java 配置类来创建
    private static void testAnnotationConfigApplicationContext() {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(Config.class);

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        System.out.println(context.getBean(Bean2.class).getBean1());
    }

    // 较为经典的容器, 基于 java 配置类来创建, 用于 web 环境
    private static void testAnnotationConfigServletWebServerApplicationContext() {
        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
    }

    @Configuration
    static class WebConfig {

        /**
         * 注册Tomcat服务器
         */
        @Bean
        public ServletWebServerFactory servletWebServerFactory(){
            return new TomcatServletWebServerFactory();
        }

        /**
         * 注册 DispatcherServlet
         */
        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        /**
         * 注册 DispatcherServlet路径 到 Tomcat 服务器上
         */
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }
        @Bean("/hello")
        public Controller controller1() {
            return (request, response) -> {
                response.getWriter().print("hello");
                return null;
            };
        }
    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(Bean1 bean1) {
            Bean2 bean2 = new Bean2();
            bean2.setBean1(bean1);
            return bean2;
        }
    }

    static class Bean1 {
    }

    static class Bean2 {

        private Bean1 bean1;

        public void setBean1(Bean1 bean1) {
            this.bean1 = bean1;
        }

        public Bean1 getBean1() {
            return bean1;
        }
    }
}

ClassPathXmlApplicationContext

较为经典的容器, 基于 classpath 下 xml 格式的配置文件来创建

	private static void testClassPathXmlApplicationContext() {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-beans.xml");

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        System.out.println(context.getBean(Bean2.class).getBean1());
    }


	// 以上代码相当于
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    System.out.println("读取之前...");
    for (String name : beanFactory.getBeanDefinitionNames()) {
        System.out.println(name);
    }
    System.out.println("读取之后...");
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    reader.loadBeanDefinitions(new ClassPathResource("spring-beans.xml"));
    for (String name : beanFactory.getBeanDefinitionNames()) {
        System.out.println(name);
    }

spring-beans.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">

    <!-- 控制反转, 让 bean1 被 Spring 容器管理 -->
    <bean id="bean1" class="com.lkl.spring.chapter2.TestApplicationContext.Bean1"/>

    <!-- 控制反转, 让 bean2 被 Spring 容器管理 -->
    <bean id="bean2" class="com.lkl.spring.chapter2.TestApplicationContext.Bean2">
        <!-- 依赖注入, 建立与 bean1 的依赖关系 -->
        <property name="bean1" ref="bean1"/>
    </bean>
</beans>

FileSystemXmlApplicationContext

基于磁盘路径下 xml 格式的配置文件来创建

	private static void testFileSystemXmlApplicationContext() {
        FileSystemXmlApplicationContext context =
                new FileSystemXmlApplicationContext(
                        "src\\main\\resources\\spring-beans.xml");
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        System.out.println(context.getBean(Bean2.class).getBean1());
    }

	// 相当于
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    System.out.println("读取之前...");
    for (String name : beanFactory.getBeanDefinitionNames()) {
        System.out.println(name);
    }
    System.out.println("读取之后...");
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    reader.loadBeanDefinitions(new FileSystemResource("src\\main\\resources\\spring-beans.xml"));
    for (String name : beanFactory.getBeanDefinitionNames()) {
        System.out.println(name);
    }

AnnotationConfigApplicationContext

较为经典的容器,基于 java 配置类来创建

	private static void testAnnotationConfigApplicationContext() {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(Config.class);

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        System.out.println(context.getBean(Bean2.class).getBean1());
    }
    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(Bean1 bean1) {
            Bean2 bean2 = new Bean2();
            bean2.setBean1(bean1);
            return bean2;
        }
    }

    static class Bean1 {
    }

    static class Bean2 {

        private Bean1 bean1;

        public void setBean1(Bean1 bean1) {
            this.bean1 = bean1;
        }

        public Bean1 getBean1() {
            return bean1;
        }
    }

AnnotationConfigServletWebServerApplicationContext

较为经典的容器,基于 java 配置类来创建,用于 web 环境【内嵌Tomcat】

	private static void testAnnotationConfigServletWebServerApplicationContext() {
        AnnotationConfigServletWebServerApplicationContext context =
                new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
    }
    @Configuration
    static class WebConfig {

        /**
         * 注册Tomcat服务器
         */
        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            return new TomcatServletWebServerFactory();
        }

        /**
         * 注册 DispatcherServlet
         */
        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        /**
         * 注册 DispatcherServlet路径 到 Tomcat 服务器上
         */
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        /**
         * 提供一个web访问接口
         */
        @Bean("/hello")
        public Controller controller1() {
            return (request, response) -> {
                response.getWriter().print("hello");
                return null;
            };
        }
    }

启动容器,访问http://localhost:8080/hello可以得到相应的响应

image-20230709015152350

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/734358.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

运动想象MI:带通滤波的Python实现

运动想象MI&#xff1a;带通滤波的Python实现 0. 引言1. 代码介绍1.1 实现方法&#xff08;1&#xff09;1.2 实现方法&#xff08;2&#xff09; 2. 函数介绍3. 滤波函数介绍4. 总结 0. 引言 在执行运动想象任务时&#xff0c;由于实际采集实验不是在完全屏蔽的环境中进行的&…

计算机体系结构基础知识介绍之高级分支预测(一)

由于需要通过分支危险和停顿来强制控制依赖&#xff0c;分支会损害管道性能。 循环展开是减少分支危险数量的一种方法&#xff1b; 我们还可以通过预测分支的行为来减少分支的性能损失。 分支预测是一种计算机技术&#xff0c;它的目的是在执行分支指令之前&#xff0c;预测分支…

人工智能三要素:算法、算力、数据

1 人工智能介绍 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是指计算机系统模拟、模仿和执行人类智能的能力。它是一门研究如何使计算机能够像人类一样思考、学习、推理和解决问题的科学和技术领域。 人工智能通过利用大量的数据和强大的计算…

ACL访问控制、Squid 反向代理

ACL访问控制、Squid 反向代理 一、ACL访问控制1、定义访问控制列表2、配置步骤 二、Squid 反向代理1、工作机制2、配置步骤 一、ACL访问控制 在配置文件 squid.conf 中&#xff0c;ACL 访问控制通过以下两个步骤来实现&#xff1a; &#xff08;1&#xff09;使用 acl 配置项定…

【我们一起60天准备考研算法面试(大全)-第八天 8/60】

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

路径规划算法:基于混沌博弈优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于混沌博弈优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于混沌博弈优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

Vue3的使用--002

Vue3包含vue2的语法&#xff0c;学习vue3就行。 前提要求&#xff0c; 安装大于node.js15.0。 创建Vue 项目 &#xff1a; npm init Vuelastest : 这一执行将会安装并执行create-vue, 他是Vue 官方的脚手架工具。你将会看到一些Typescript 和测试支持之类的可选功能提示&…

在VSCode里使用Jupyter?Notebook调试Java代码的详细过程

目录 什么是Jupyter Notebook&#xff1f;Jupyter Notebook主要优点环境准备下载 IJava创建conda虚拟环境搭建运行环境测试 之前使用的那台电脑有点旧了&#xff0c;稍微跑一下程序就报内存不够。本来想考虑入手一台带GPU的新电脑&#xff0c;在商品浏览里的时候&#xff0c;…

DynaSLAM代码详解(1) — RGBD模式DynaSLAM运行流程

目录 1.1 DynaSLAM和ORB-SLAM2文件对比 1.2 RGBD模式运行流程 论文翻译地址&#xff1a;动态SLAM论文(2) — DynaSLAM: Tracking, Mapping and Inpainting in Dynamic Scenes_几度春风里的博客-CSDN博客 1.1 DynaSLAM和ORB-SLAM2文件对比 DynaSLAM是一个建立在ORB-SLAM2基础上…

【Leetcode】707. 设计链表

单向链表 class ListNode:def __init__(self, val0, nextNone):self.val valself.next nextclass MyLinkedList:def __init__(self):self.dummy_head ListNode()self.size 0def get(self, index):if index < 0 or index > self.size:return -1current self.dummy_h…

【简单认识LVS+Keepalived负载均衡高可用群集】

文章目录 一、Keepalived高可用详解1、简介2、原理3、Keepalived体系主要模块及其作用&#xff1a; 二、LVSKeepalived 高可用群集部署实例1.配置NFS共享存储器2.配置节点web服务&#xff08;两台的配置相同&#xff09;&#xff08;1&#xff09;配置虚拟 IP 地址&#xff08;…

飞桨黑客松 OpenVINO™ 任务获奖者经验分享 | 基于OpenVINO™ 与PaddleOCR的结构化输出Pipeline...

点击蓝字 关注我们,让开发变得更有趣 作者 | 张一乔 排版 | 李擎 OpenVINO™ 1. 黑客松活动介绍 01 第四季飞桨黑客松(PaddlePaddle Hackathon Season 4)是由百度联合合作伙伴共同举办的开源深度学习框架类黑客松活动。本次活动旨在为全球开发者提供一个交流、合作和创新的机会…

Django_模型类详解(七)

目录 一、定义属性 字段类型 选项 二、查询集 两大特性 查询集的缓存 限制查询集 三、条件查询 条件运算符 1) 查询相等 2) 模糊查询 3) 空查询 4) 范围查询 5) 比较查询 6) 日期查询 F对象 Q对象 聚合函数 四、关联查询 通过对象执行关联查询 通过模型类执…

线程池介绍

1、什么是线程池 例子&#xff1a; 10年前单核CPU电脑&#xff0c;假的多线程&#xff0c;像马戏团小丑玩多个球&#xff0c;CPU需要来回切换。 现在是多核电脑&#xff0c;多个线程各自跑在独立的CPU上&#xff0c;不用切换效率高。 线程池的优势&#xff1a; 线程池做的工作…

七、VPN技术之密码学基础(密码体制、对称加密算法、非对称加密算法)

更多网络基础内容可见: 网络基础学习目录及各章节指引 7.1 密码学基础 7.1.1 基础概念 密码:对文本进行编码,使偷窥者无法识别的算法。是一套编码方案,一种特殊的报文编码和相应的解码方式的结合体。 加密之前的原始报文称为明文,使用密码之后的报文叫密文。一个简单的例…

elk高并发架构

1.前言 普通的elk架构只适合数据量小的情景&#xff0c;而且也不安全&#xff0c;在瞬时数据量大的情况下可能会导致logstash崩溃&#xff0c;从而导致数据的丢失&#xff0c;对于数据安全有较高要求&#xff0c;可以在架构中加入消息队列&#xff0c;既可以防止瞬时的大流量并…

有过JVM调优经验吗【面试题】

写作目的 JVM其实比较偏理论的&#xff0c;日常工作中很少遇到。但是面试他问&#xff0c;所以需要自己mock一下场景进行准备这个问题的回复。 本次分析的场景的元空间太小导致频繁FGC的问题。 源码&启动参数 gitee下载源码 启动-调优前 nohup java -XX:MetaspaceS…

【MySQL】SQL索引失效的几种场景及优化

MySQL中提高性能的一个最有效的方式是对数据表设计合理的索引。索引提供了高效访问数据的方法&#xff0c;并且加快查询的速度&#xff0c; 因此索引对查询的速度有着至关重要的影响。 使用索引可以快速地定位表中的某条记录&#xff0c;从而提高数据库查询的速度&#xff0c;…

C++之函数模板高级用法(一百五十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

两个好用到爆的Python模块,建议收藏!

在日常开发工作中&#xff0c;经常会遇到这样的一个问题&#xff1a;要对数据中的某个字段进行匹配&#xff0c;但这个字段有可能会有微小的差异。比如同样是招聘岗位的数据&#xff0c;里面省份一栏有的写“广西”&#xff0c;有的写“广西壮族自治区”&#xff0c;甚至还有写…