其他分享
首页 > 其他分享> > 04 Spring中BeanFactory与ApplicationContext接口及实现类特点

04 Spring中BeanFactory与ApplicationContext接口及实现类特点

作者:互联网

1 接口

1-1 基本接口说明

Springboot启动源码

package com.village.dog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {
    private static final Logger logging = LoggerFactory.getLogger(Application.class);
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
    }
}

图1:Diagram for BeanFactory

BeanFactory接口:用于访问Spring容器的根接口

简介:实现BeanFactory接口的Object容纳多个bean definition,
每个bean definition通过唯一的字符串名称进行区别。

ApplicationContext接口:为应用提供配置的核心接口

接口支持功能 所对应的父接口
用于访问应用组件的工厂方法 org.springframework.beans.factory.ListableBeanFactory
加载文件资源的能力 org.springframework.core.io.ResourceLoader
向已注册的监听对象发布事件的能力 ApplicationEventPublisher
解析消息,支持国际化 MessageSource

说明:类图中可看到ApplicationContext接口继承BeanFactory接口,此外还继承了其他很多接口。

Java中接口可通过extends关键字继承一个或多个接口
官方文档对上述接口的说明:
BeanFactory:

1-2 BeanFactory实现类

图2:Diagram for DefaultLisableBeanFactory

DefaultLisableBeanFactory:spring中的默认接口实现类

// 说明:DefaultSingletonBeanRegister中定义了存放所有单例对象的concurrentHashMap
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

需求:打印 ”存放单例对象的map“中特定的单例对象

package com.village.dog;
import org.springframework.stereotype.Component;
// springboot默认是单例对象
@Component
public class Component1 {
}
package com.village.dog;
import org.springframework.stereotype.Component;
@Component
public class Component2 {
}
package com.village.dog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.lang.reflect.Field;
import java.util.Map;

@SpringBootApplication
public class Application {
    private static final Logger logging = LoggerFactory.getLogger(Application.class);
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);

        /*
            需求:通过反射的方式获取存储单例对象的concurrentMap,打印处Map中我们自己注入的
                  两个单例对象Component1和Component2.
        */
        Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        singletonObjects.setAccessible(true);
        // 获取现有的BeanFactory实现类
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 获取该实现类的singletonObjects属性,也就是存放单例对象的map
        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())
        );
    }
}

运行结果

component1=com.village.dog.Component1@601cbd8c
component2=com.village.dog.Component2@7180e701

1-3 ApplicationContext接口特点

图2中ApplicationContext的父接口如下

ListableBeanFactory和HierarchicalBeanFactory:BeanFactory的扩展
MessageSource: 用于解析消息的策略接口,支持消息参数化和国际化(国际化能力)
EnvironmentCapable:环境信息,包括yaml,xml等类型文件中的配置信息
ApplicationEventPublisher:事件对象发布能力
ResourcePatternResolver:基于通配符匹配资源

说明:可以发现Application除了获取Bean实例对象这一基本的功能外,还支持国际化,环境信息获取、
基于通配符匹配资源和发布事件对象
这四种能力。

四种扩展功能测试代码

package com.village.dog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
// springboot默认是单例对象
@Component
public class Component1 {
    private static final Logger log = LoggerFactory.getLogger(Component1.class);

    /*
       通过事件分发器,可以实现业务上解耦:
       比如用户注册,后续操作可能有短信验证码,邮件验证码
       这个时候模块的功能的协同可以通过事件发布框架进行接口
     */
    @EventListener
    public void testMonitor(UserRegisterEvent event){
        log.info("收到发送的消息{}",event);
    }
}
package com.village.dog;
import org.springframework.context.ApplicationEvent;
public class UserRegisterEvent extends ApplicationEvent {
    public UserRegisterEvent(Object source){
        super(source);
    }
}
package com.village.dog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.util.Locale;

@SpringBootApplication
public class Application_Extension {
    private static final Logger logging = LoggerFactory.getLogger(Application_Extension.class);
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        ConfigurableApplicationContext context = SpringApplication.run(Application_Extension.class,args);
        /*
           1) ApplicationContext国际化功能:
           ========该继承于父接口MessageSource=====
           getMessage方法:同一key获取不同语言的value,从而实现国际化
           实际开发中,语言可以从浏览器的请求头获取
           注意:配置文件内容的编码方式需要设置的方式一致,IDEA中可以在setting中设置properties文件的编码方式为UTF8
         */
        System.out.println("1 国际化功能测试");
        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));
        System.out.println();
        /*
           2) ApplicationContext:获取资源文件
           ========继承于于父接口MessageSource=====
         */
        System.out.println("2 获取资源测试");
        Resource[] resources = context.getResources("classpath:application.properties");
        for(Resource resource:resources){
            System.out.println(resource);
        }
        /*采用通配符获取jar包中名称为spring.factories的文件路径
          spring.factories的作用:https://zhuanlan.zhihu.com/p/444331676
         */
        Resource[] re = context.getResources("classpath*:META-INF/spring.factories");
        for(Resource resource:re){
            System.out.println(resource);
        }
        System.out.println();

        /*
            3) applicationContext的环境信息获取能力
            =============继承于父接口EnvironmentCapable====
         */
        // 配置信息获取:通过application获取windows系统环境变量Java_Home以及application.properties中的server.port属性
        System.out.println("3 环境信息获取测试");
        System.out.println(context.getEnvironment().getProperty("Java_Home"));
        System.out.println(context.getEnvironment().getProperty("server.port"));
        System.out.println();

        /*
           4) applicationContext的事件发布能力
           ==============继承于父接口ApplicationEventPublisher===
         */
        System.out.println("4 事件对象发布测试");
        context.publishEvent(new UserRegisterEvent(context));
    }
}

运行结果

1 国际化功能测试
你好
Hello
こんにちは

2 获取资源测试
class path resource [application.properties]
URL [jar:file:/C:/Users/Administrator/.m2/repository/org/springframework/boot/spring-boot/2.5.5/spring-boot-2.5.5.jar!/META-INF/spring.factories]
URL [jar:file:/C:/Users/Administrator/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.5.5/spring-boot-autoconfigure-2.5.5.jar!/META-INF/spring.factories]
URL [jar:file:/C:/Users/Administrator/.m2/repository/org/springframework/spring-beans/5.3.10/spring-beans-5.3.10.jar!/META-INF/spring.factories]
URL [jar:file:/C:/Users/Administrator/.m2/repository/org/springframework/boot/spring-boot-test/2.5.5/spring-boot-test-2.5.5.jar!/META-INF/spring.factories]

3 环境信息获取测试
C:\Program Files\Java\jdk1.8.0_131
9006

4 事件对象发布测试
[2022-05-17 16:03:06] [INFO ] -- 收到发送的消息com.village.dog.UserRegisterEvent[source=org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@67080771

2 实现类

2-1 BeanFactory实现类特点

特点1:底层类,相较于Application不支持以下功能
    不会主动调用BeanFactory的后处理器
    不会主动添加Bean后处理器(解析@Autowired @Resource注入依赖)
    不会主动初始化单例
    不会解析${}和#{}(EL表达式)
特点2:Bean的后置处理器支持排序功能

BeanFactory实现类特点展示代码

package com.village.dog;
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.context.annotation.Configuration;


public class TestBeanFactory {
    private static void printBeanDefinitionsNames(DefaultListableBeanFactory beanFactory){
        for(String name:beanFactory.getBeanDefinitionNames()){
            System.out.println(name);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        /*
           容器创建实例对象前必须存储对象的beanDefinition
           beanDefinition包含class、scope、初始化、销毁信息
         */
        AbstractBeanDefinition beanDefinition =
        BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config",beanDefinition);

        /*
           打印容器类中BeanDefinition的名称,从打印结果可以发现
           容器类并没有对Bean的内容进行进一步解析。
         */
        System.out.println("step1:当前容器所包含的BeanDefinition");
        printBeanDefinitionsNames(beanFactory);

        // 为容器添加处理器
        System.out.println("step2:容器添加处理器后,所包含的BeanDefinition");
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        printBeanDefinitionsNames(beanFactory);

        System.out.println("step3:执行BeanFactoryPostProcessor逻辑后,添加的BeanDefinition,创建的实例对象和");
        // 执行BeanFactoryPostProcessor的逻辑
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor ->{
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });
        printBeanDefinitionsNames(beanFactory);

        // 为null,说明此时@Autowired的,如果在执行BeanPostProcessor前获取bean,那么后续即便
        // 调用BeanPostProcessor也无法注入依赖
        //System.out.println(beanFactory.getBean(Bean1.class).getBean2());
        // 执行BeanPostProcessor的逻辑,将依赖注入到容器的bean中,针对bean的生命周期的各个阶段提供扩展
        // 例如@Autowired或@Resource
        System.out.println("step4:执行BeanPostProcessor,创建的实例对象");
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
        // DefaultListableBeanFactory默认是延迟创建单例,可以通过preInstantiateSingletons提前创建
        beanFactory.preInstantiateSingletons();
        System.out.println("=============================");
        System.out.println(beanFactory.getBean(Bean1.class).getBean2());

        /*
           总结:BeanFactory的特点:
                 1.不会主动调用BeanFactory的后处理器
                 2.不会主动添加Bean后处理器
                 3.不会主动初始化单例
                 4.不会解析EL表达式
         */
   }

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

    }

    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;}
    }

    static class Bean2{
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);
        public Bean2(){
            log.debug("构造Bean2()");
        }
    }
}

程序输出结果

step1:当前容器所包含的BeanDefinition
config

step2:容器添加处理器后,所包含的BeanDefinition
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory

step3:执行BeanFactoryPostProcessor逻辑后,添加的BeanDefinition,创建的实例对象和
[2022-05-19 20:43:30] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
[2022-05-19 20:43:30] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
[2022-05-19 20:43:30] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
bean1
bean2

step4:执行BeanPostProcessor,创建的实例对象
[2022-05-19 20:43:30] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
[2022-05-19 20:43:30] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
[2022-05-19 20:43:30] [DEBUG] -- Creating shared instance of singleton bean 'config'
[2022-05-19 20:43:30] [DEBUG] -- Creating shared instance of singleton bean 'bean1'
[2022-05-19 20:43:30] [DEBUG] -- 构造Bean1()
[2022-05-19 20:43:30] [DEBUG] -- Creating shared instance of singleton bean 'bean2'
[2022-05-19 20:43:30] [DEBUG] -- 构造Bean2()
=============================
com.village.dog.TestBeanFactory$Bean2@61862a7f


实例程序说明

DefaultListableBeanFactory()是BeanFactory接口实现,这个类也就是
产生Bean的工厂,该工厂能够创建bean的实例对象供外部程序使用。为创建
Bean的实例对象,该工厂需要解析每个bean的class对象,从而为每个bean生成
beanDefinition存放在工厂中(BeanDefinition是对bean实例的描述,包括属性值、构造参数值等)。

显然"如何从Bean得到BeanDefinition"对于BeanFactory非常重要,只要我们保证能够正确解析Bean Class获取BeanDefinition实例对象,那么就能够保证我们能够正确的创建想要的bean。

实际开发中,我们可以通过注解的方式将我们定义的Bean放入的容器中,具体的工作实际上是由Spring中的BeanFactoryPostProcessor去解析Bean生成BeanDefinition,通过BeanPostProcessor为bean实例对象注入依赖。

设计思想:在程序的固定固定位置通过hook程序的定义修改实现灵活的功能,是开闭原则的一种体现

Bean后处理器的排序
package com.village.dog;
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.context.annotation.Configuration;

import javax.annotation.Resource;


public class TestBeanFactory {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        AbstractBeanDefinition beanDefinition =
        BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config",beanDefinition);
        // 为容器添加处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        // 执行BeanFactoryPostProcessor的逻辑
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor ->{
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
//        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanPostProcessor->{
//            System.out.println("BeanFactory中的BeanPostProcessor:"+beanPostProcessor);
//            beanFactory.addBeanPostProcessor(beanPostProcessor);     // 先添加的processor先执行
//        });

        // 重新定义BeanPostProcessor的顺序
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream().sorted(beanFactory.getDependencyComparator()).
                forEach(beanPostProcessor->{
            System.out.println("BeanFactory中的BeanPostProcessor:"+beanPostProcessor);
            beanFactory.addBeanPostProcessor(beanPostProcessor);     // 先添加的processor先执行
        });

        System.out.println(beanFactory.getBean(Bean1.class).getBean3());

   }

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

    }

    /*
       Bean1中Inter bean3,Inter接口有两个实现类
       Bean3,Bean4,
       情况1:
       @Autowired
       Inter bean3
       会根据bean3名称匹配到Bean3

       情况2:
        @Resource(name="bean4")
        Inter bean3;
        会根据name匹配到bean4

        上述如果两个注解一起用,都可以匹配,但最终匹配的是Bean3,原因是
        @Autowired对应的BeanPostProcessor在执行顺序上优于
        @Resource对应的BeanPostProcessor
        我们可以通过定义排序规则,让@Resource对应的BeanPostProcessor的执行顺序优于
        @Autowired对应的BeanPostProcessor
    */
    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")
        Inter bean3;
        public Inter getBean3(){return bean3;}
    }

    static class Bean2{
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);
        public Bean2(){
            log.debug("构造Bean2()");
        }
    }

    interface Inter{
        void get();
    }

    static class Bean3 implements Inter{
        @Override
        public void get() {}
    }

    static class Bean4 implements Inter{
        @Override
        public void get() {

        }
    }

}

2-2 ApplicationContext接口的实现类

背景:Spring中ApplicationContext接口有以下四个较为常见的实现类

容器类名 作用
ClassPathXmlApplication 加载classpath路径下的xml进行配置
FileSystemXmlApplicationContext 加载磁盘路径下的xml文件进行配置
AnnotationConfigApplicationContext 基于Java配置类创建
AnnotationConfigServletWebServerApplicationContext 基于Java配置类创建,适用于web环境

四种实现类测试代码

package com.village.dog;

import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.Controller;

public class TestApplicationContext {
    public static void main(String[] args) {
        System.out.println("测试ClassPathXmlApplicationContext");
        testClassPathXmlApplicationContext();

        /*
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // ==================ClassPathXmlApplication的内部机制流程=================
        printBeanDefinitionNames(beanFactory);
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(new ClassPathResource("b01.xml"));
        printBeanDefinitionNames(beanFactory);
        */
        System.out.println("测试AnnotationConfigApplicationContext");
        testAnnotationConfigApplicationContext();

        System.out.println("测试AnnotationConfigServletWebServerApplicationContext");
        testAnnotationConfigServletWebServerApplicationContext();

    }


    /*
            ClassPathXmlApplication:加载classpath路径下的xml进行配置
            FileSystemXmlApplicationContext:加载磁盘路径下的xml文件进行配置
     */
    private static void testClassPathXmlApplicationContext(){
        // FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("xxx.xml");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("b01.xml");
        printBeanDefinitionNames(context);
        System.out.println(context.getBean(Bean2.class).getBean1());
        System.out.println();

    }




    private static void testAnnotationConfigApplicationContext(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        /*
           从输出可以看出:相较于ClassPathXmlApplication容器,该容器中除了配置类中配置的
           Bean1和Bean2,还有Config以及用于解析不同注解的5个工具类,作为bean的后处理器(如下所示):
           org.springframework.context.annotation.internalConfigurationAnnotationProcessor
           org.springframework.context.annotation.internalAutowiredAnnotationProcessor
           org.springframework.context.annotation.internalCommonAnnotationProcessor
           org.springframework.context.event.internalEventListenerProcessor
           org.springframework.context.event.internalEventListenerFactory

           如果ClassPathXmlApplication加载的xml文件中包含<context:annotation-config/>,则也能引入上述5个后置处理器

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

    /*
      AnnotationConfigServletWebServerApplicationContext:
                            该容器也是基于Java配置类创建,主要用于web环境
     */
    private static void testAnnotationConfigServletWebServerApplicationContext(){

        // 内嵌Tomcat容器配合DispatchServlet实现简单的web应用
        // 最小系统: web容器,servlet对象,容器注册类,控制类处理请求
        AnnotationConfigServletWebServerApplicationContext  context = new AnnotationConfigServletWebServerApplicationContext (WebConfig.class);
        printBeanDefinitionNames(context);
        System.out.println();
    }

    @Configuration
    static class WebConfig{
        @Bean
        public ServletWebServerFactory servletWebServerFactory(){  // 创建内嵌Tomcat容器
            return new TomcatServletWebServerFactory();
        }

        @Bean
        public DispatcherServlet dispatcherServlet(){              // 创建Servlet对象
            return new DispatcherServlet();
        }

        // 将dispatchServlet注册到Tomcat容器中
        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet){
            return new DispatcherServletRegistrationBean(dispatcherServlet,"/");
        }

        // 这里将/后面的bean名称作为访问路径
        @Bean("/hello")
        public Controller controller1(){
            return (request,response)->{
                    response.getWriter().print("Response Message: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;
        }

    }

    private static void printBeanDefinitionNames(ListableBeanFactory beanFactory){
        System.out.println("==============beanDefinitions==================");
        for(String name:beanFactory.getBeanDefinitionNames()){
            System.out.println(name);
        }
        System.out.println("================================");
    }
}


日志输出

测试ClassPathXmlApplicationContext
[2022-06-01 20:26:57] [DEBUG] -- Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5afa04c
[2022-06-01 20:26:57] [DEBUG] -- Loaded 2 bean definitions from class path resource [b01.xml]
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'bean1'
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'bean2'
==============beanDefinitions==================
bean1
bean2
================================
com.village.dog.TestApplicationContext$Bean1@475e586c

测试AnnotationConfigApplicationContext
[2022-06-01 20:26:57] [DEBUG] -- Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5c1a8622
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'testApplicationContext.Config'
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'bean1'
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'bean2'
[2022-06-01 20:26:57] [DEBUG] -- Autowiring by type from bean name 'bean2' via factory method to bean named 'bean1'
==============beanDefinitions==================
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testApplicationContext.Config
bean1
bean2
================================
com.village.dog.TestApplicationContext$Bean1@21b2e768

测试AnnotationConfigServletWebServerApplicationContext
[2022-06-01 20:26:57] [DEBUG] -- Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@11c9af63
[2022-06-01 20:26:57] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
[2022-06-01 20:26:58] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
[2022-06-01 20:26:58] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
[2022-06-01 20:26:58] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
[2022-06-01 20:26:58] [DEBUG] -- Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
[2022-06-01 20:26:58] [DEBUG] -- Unable to locate ThemeSource with name 'themeSource': using default [org.springframework.ui.context.support.ResourceBundleThemeSource@be35cd9]
[2022-06-01 20:26:58] [DEBUG] -- Creating shared instance of singleton bean 'servletWebServerFactory'
[2022-06-01 20:26:58] [DEBUG] -- Creating shared instance of singleton bean 'testApplicationContext.WebConfig'
[2022-06-01 20:27:00] [DEBUG] -- Code archive: C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot\2.5.5\spring-boot-2.5.5.jar
[2022-06-01 20:27:00] [DEBUG] -- Code archive: C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot\2.5.5\spring-boot-2.5.5.jar
[2022-06-01 20:27:00] [DEBUG] -- None of the document roots [src/main/webapp, public, static] point to a directory and will be ignored.
[2022-06-01 20:27:00] [INFO ] -- Tomcat initialized with port(s): 8080 (http)
六月 01, 2022 8:27:00 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-nio-8080"]
六月 01, 2022 8:27:00 下午 org.apache.catalina.core.StandardService startInternal
信息: Starting service [Tomcat]
六月 01, 2022 8:27:00 下午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet engine: [Apache Tomcat/9.0.53]
六月 01, 2022 8:27:00 下午 org.apache.catalina.core.ApplicationContext log
信息: Initializing Spring embedded WebApplicationContext
[2022-06-01 20:27:00] [DEBUG] -- Published root WebApplicationContext as ServletContext attribute with name [org.springframework.web.context.WebApplicationContext.ROOT]
[2022-06-01 20:27:00] [INFO ] -- Root WebApplicationContext: initialization completed in 2448 ms
[2022-06-01 20:27:00] [DEBUG] -- Creating shared instance of singleton bean 'registrationBean'
[2022-06-01 20:27:00] [DEBUG] -- Creating shared instance of singleton bean 'dispatcherServlet'
[2022-06-01 20:27:00] [DEBUG] -- Autowiring by type from bean name 'registrationBean' via factory method to bean named 'dispatcherServlet'
[2022-06-01 20:27:00] [DEBUG] -- Mapping filters: 
[2022-06-01 20:27:00] [DEBUG] -- Mapping servlets: dispatcherServlet urls=[/]
[2022-06-01 20:27:00] [DEBUG] -- Creating shared instance of singleton bean '/hello'
[2022-06-01 20:27:00] [DEBUG] -- Starting beans in phase 2147483646
六月 01, 2022 8:27:00 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-nio-8080"]
[2022-06-01 20:27:00] [INFO ] -- Tomcat started on port(s): 8080 (http) with context path ''
[2022-06-01 20:27:00] [DEBUG] -- Successfully started bean 'webServerStartStop'
[2022-06-01 20:27:00] [DEBUG] -- Starting beans in phase 2147483647
[2022-06-01 20:27:00] [DEBUG] -- Successfully started bean 'webServerGracefulShutdown'
==============beanDefinitions==================
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
testApplicationContext.WebConfig
servletWebServerFactory
dispatcherServlet
registrationBean
/hello
================================

总结:四种ApplicationContext接口的实现类包含两种配置容器的方式,一种是基于xml文件,另外一种是通过添加配置注解的配置类。通常我们适用配置类的方式配置容器更多一点。通过打印容器中beanDefinition。可以发现采用配置类的容器类对于@Autowired等注解的解析是通过容器中所添加的后置bean处理器实现的。
此外,web环境下的容器类至少包含 web容器、servlet对象、web容器注册对象。

小结

问题1:BeanFactory与ApplicationContext的作用和关系

1)BeanFactory是spring容器的核心接口,也是ApplicationContext的父接口。
2)ApplicationContext组合BeanFactory的功能,更加确切地ApplicationContext接口的实现类内部
有一个成员变量是BeanFactory接口的实现类,然后通过内部BeanFactory的实现类调用BeanFactory接口方法。
说明:org.springframework.context.support.GenericApplicationContexts是ApplicationContext接口的实现类,其包含成员变量DefaultListableBeanFactory,该变量实现BeanFactory接口。因此Application接口本质上组合了BeanFactory接口。
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
	private final DefaultListableBeanFactory beanFactory;
		...
	}

问题2:ApplicationContext在BeanFactory扩展哪些功能?

ApplicationContext除了继承BeanFactory,还继承了其他接口,从而
支持以下四种功能:

1)国际化功能
2)根据统配符加载Resouce的功能
3)获取配置信息(环境变量)的功能
4)发送事件对象的功能

问题3:ApplicationContext的事件解耦功能如何得到支持?

事件解耦本质上是观察者模式的体现,通过消息,实现功能的解耦。
ApplicationContext的父接口ApplicationContext提供了该功能。

Spring 事件驱动模型实现业务解耦
观察者模式与订阅发布模式的区别

问题4:BeanFactory实现类的特点?

属于底层类,相较于Application不支持以下功能

参考资料

spring5讲解视频

循环依赖介绍

标签:ApplicationContext,04,BeanFactory,springframework,bean,context,import,org,class
来源: https://www.cnblogs.com/kfcuj/p/16336304.html