springboot源码分析(1)BeanFactory与ApplicationContext的区别与联系,容器实现特点

一、BeanFactory与ApplicationContext的区别与联系
BeanFactory是ApplicationContext的父接口
它是Spring的核心容器,主要的ApplicationContext实现都【组合】了它的功能
BeanFactory实际上是ApplicationContext的成员变量
表面上只有getBean,实际上控制反转、基本的依赖注入、直至Bean的生命周期的各种功能,都由它的实现类提供请添加图片描述
二、容器实现
1.BeanFactory实现的特点
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//bean的定义(class,scope,初始化,销毁)
AbstractBeanDefinition beanDefinition =
BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope(“singleton”).getBeanDefinition();
beanFactory.registerBeanDefinition(“config”, beanDefinition);

    //给BeanFactory添加一些常用的后处理器,将后处理器加到BeanFactory中
    AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

    //获取内置后处理器
    //beanFactory后处理器主要功能,补充了一些bean定义
    beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(beanFactoryPostProcessor -> {
        beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
    });
    //Bean 后处理器 ,针对bean的生命周期的各个阶段提供扩展,例如 @Autowired @Resource   这里是建立BeanFactory和后处理器的联系
    beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);

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

    //提前准备好所有单例对象
    beanFactory.preInstantiateSingletons();
    System.out.println(beanFactory.getBean(Bean1.class).getBean2());
}

学到了什么:

beanFactory 不会做的事
不会主动调用BeanFactory后处理器
不会主动添加Bean后处理器
不会主动初始化单例
不会解析BeanFactory 还不会解析${}与#{}
bean后处理器会有排序的逻辑
2.ApplicationContext的常见实现和用法
四个ApplicationContext接口的实现类:

ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
AnnotationConfigApplicationContext
AnnotationConfigServletWebServerApplicationContext
四个接口的测试代码如下:

//较为经典的容器,基于classpath下xml格式的配置文件来创建
private static void testClassPathXmlApplicationContext(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(“b01.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\\b01.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);

}

@Configuration
static class WebConfig{
    @Bean
    public ServletWebServerFactory servletWebServerFactory(){
        return new TomcatServletWebServerFactory();
    }
    @Bean
    public DispatcherServlet dispatcherServlet(){
        return new DispatcherServlet();
    }
    @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的内部实现:

//内部实现
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(“b01.xml”));
for (String name : beanFactory.getBeanDefinitionNames()) {
System.out.println(name);
}
(FileSystemXmlApplicationContext和ClassPathXmlApplicationContext的内部实现基本类似,导入xml文件方式不同)

学到了什么:

常见的ApplicationContext容器实现
内嵌容器、DispatcherServlet的创建方法、作用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值