02.容器实现BeanFactory和ApplicationContext实现

容器实现BeanFactory和ApplicationContext实现

  1. BeanFactory实现的特点
  2. ApplicationContext的常见实现和用法
  3. 内嵌容器、注册DispatcherServlet

1. BeanFactory的实现

  1. BeanFactory不会主动添加BeanFactoryPostProcessor;BeanFactory后处理器主要功能:补充了一些Bean的定义,例如扫描@Configuration注解
  2. BeanFactory不会主动添加BeanPostProcessor;Bean后处理器主要功能:针对bean的生命周期的各个阶段提供扩展,例如@Autowired、@Resource、@Value
  3. BeanFactory添加了后处理器的的定义后,不会主动创建这些后处理的对象(不会主动使用),需要调用对应的方法将BeanFactory和后处理器们关联起来
  4. 不会主动初始化单例,默认懒汉单例,用到了才会创建;beanFactory.preInstantiateSingletons()方法修改为饿汉单例

补充:

  1. 创建BeanDefinition

    AbstractBeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();

  2. 注册BeanDefinition

    beanFactory.registerBeanDefinition("config", definition);

  3. 给BeanFactory添加一些常用的后处理器

    AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

    添加的后处理器

    • org.springframework.context.annotation.internalConfigurationAnnotationProcessor

      用来解析@Configuration注解

    • org.springframework.context.annotation.internalAutowiredAnnotationProcessor

      用来解析@Autowire注解

    • org.springframework.context.annotation.internalCommonAnnotationProcessor

      用来解析@Resource注解

    • org.springframework.context.event.internalEventListenerProcessor

    • org.springframework.context.event.internalEventListenerFactory

  4. 将BeanFactoryPostProcessor初始化到beanFactory

    beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);

  5. 将BeanPostProcessor初始化到beanFactory

    beanFactory.addBeanPostProcessor(beanPostProcessor);

  6. 将spring初始化Bean方式改为饿汉单例

beanFactory.preInstantiateSingletons();

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

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // BeanFactory里存放的是Bean的定义,而不是现成的对象;Bean的定义的要素:class、scope、初始化方法、销毁方法
        AbstractBeanDefinition definition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        // 注册BeanDefinition
        beanFactory.registerBeanDefinition("config", definition);

        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            /**
             * config
             */
        }


        // 给BeanFactory添加一些常用的后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            /**
             * 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
             */
        }


        // BeanFactory后处理器BeanFactoryPostProcessor主要功能:补充了一些Bean的定义
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            /**
             * 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
             * getBean1
             * getBean2
             */
        }


        // Bean 后处理器, 针对 bean 的生命周期的各个阶段提供扩展, 例如 @Autowired @Resource ...
        System.err.println(beanFactory.getBean(Bean1.class).getBean2());
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
        System.err.println(beanFactory.getBean(Bean1.class).getBean2());

        beanFactory.preInstantiateSingletons(); // 准备好所有单例;默认懒汉单例,用到了才会创建,调用该方法修改为饿汉单例
        System.out.println(beanFactory.getBean(Bean1.class).getBean2());




        /*
            学到了什么:
            a. beanFactory 不会做的事
                   1. 不会主动调用 BeanFactory 后处理器
                   2. 不会主动添加 Bean 后处理器
                   3. 不会主动初始化单例
                   4. 不会解析beanFactory 还不会解析 ${ } 与 #{ }
         */
    }

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

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

    static class Bean1 {

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

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }
    }

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

}

2. BeanFactory-后处理器排序

首先我们验证一个问题:

  1. @Autowire注解根据类型注入,@Resource注解根据Bean的名称注入;

    当有两个同类型的Bean时,@Autowire会寻找跟变量名相同的注解进行注入(找不到则抛出异常)

  2. 如果一个成员变量上同时存在@Autowire、@Resource,并且有两个同类型的Bean,那么最终注入的是哪个?

    例如有两个Bean类型的Bean,名称bean1、bean2,成员变量名称bean1,@Resource注解指定注入bean2

  3. 结果是@Aurowire生效,@Resource失效,失效原因是被覆盖

以上问题的原因是:

  1. 每一个后处理器都有一个order,这些后处理器会根据order进行排序,order小的在前,先被执行;
  2. @Autowire由AutowiredAnnotationBeanPostProcessor处理,该处理器的优先级是Ordered.LOWEST_PRECEDENCE - 2;@Resource由CommonAnnotationBeanPostProcessor处理,该处理器的优先级是Ordered.LOWEST_PRECEDENCE - 3
  3. 因此@Resource对应的后处理器order更小,先被执行,然后后执行的@Autowire覆盖掉

我们也可以手动调整顺序,但是没有必要;以下是相关源码

  1. AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

    这里包含了添加Comparator方式的代码

  2. beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);

    传入一个比较器,该比较器实现了Comparator接口,在该比较器中重写了compare方法,内部实际上比较各个后处理器的order

  3. 每个后处理器都实现了Ordered接口,Ordered中有个getOrder()方法,返回各个后处理器的order大小

    public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
    MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware

  4. 获取到beanPostProcessors,得到list,调整顺序后再挨个添加到beanFactory中,就可以得到跟上文相反的结果

beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
	.sorted(beanFactory.getDependencyComparator())
	.forEach(beanPostProcessor -> {
		System.out.println(">>>>" + beanPostProcessor);
		beanFactory.addBeanPostProcessor(beanPostProcessor);
    });
public class A022 {
    private static final Logger log = LoggerFactory.getLogger(A022.class);

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        AbstractBeanDefinition definition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config", definition);

        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
                .sorted(beanFactory.getDependencyComparator())
                .forEach(beanPostProcessor -> {
                    System.out.println(">>>>" + beanPostProcessor);
                    beanFactory.addBeanPostProcessor(beanPostProcessor);
                });
    }

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

}

3. 四种经典的ApplicationContext实现

  1. ClassPathXmlApplicationContext

    支持读取类路径下的 XML格式bean配置文件的Web容器

  2. FileSystemXmlApplicationContext

    支持读取文件系统下的XML格式bean配置文件的Web容器

  3. AnnotationConfigApplicaitonContext

    支持读取@Config、@Resource、@Autowire、@Value等注解的Web容器

  4. AnnotaionConfigServletWebServerApplicaitonContext

    在AnnotationConfigApplicaitonContext的基础上,增加了对web应用的支持,可以接收和响应请求

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

    private static void testClassPathXmlApplicationContext() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("a023.xml");
        for (String name : context.getBeanDefinitionNames()) {
            System.err.println(name);
        }

    }

    private static void testFileSystemXmlApplicationContext() {
//        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("E:\\allproject\\spring\\src\\main\\resources\\a023.xml");
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/a023.xml");
        for (String name : context.getBeanDefinitionNames()) {
            System.err.println(name);
        }
    }

    private static void testAnnotationConfigApplicationContext() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        for (String name : context.getBeanDefinitionNames()) {
            System.err.println(name);
        }
    }

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

    static class Bean1 {
    }

    static class Bean2 {


        private A023.Bean1 bean1;

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

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

    @Configuration
    static class Config {

        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

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

    @Configuration
    static class WebConfig {

        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            // 初始化一个内嵌的tomcat
            return new TomcatServletWebServerFactory();
        }

        @Bean
        public DispatcherServlet dispatcherServlet() {
            // 转发请求至对应的servlet
            return new DispatcherServlet();
        }

        @Bean
        public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
            // 将请求转发器关联到tomcat容器
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        @Bean("/hello")
        public Controller controller1() {
            // spring约定如果Bean的名字/开头则是一个servlet
            return (request, response) -> {
                response.getWriter().write("hello");
                return null;
            };
        }
    }
}
<?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.shunyum.a02.A023.Bean1"/>

    <!-- 控制反转, 让 bean1 被 Spring 容器管理 -->
    <bean id="bean2" class="com.shunyum.a02.A023.Bean2">
        <property name="bean1" ref="bean1"/>
    </bean>
</beans>

4. ApplicationContext内部做的事

application内部组合了beanFactory,实际上bean的定义是由内部beanFactory实现;

下面的例子就是ClasspathXml ApplicationContext中的beanFactory做了哪些事;

同理,AnnotationConfigApplicationContext中的beanFactory做了哪些事可以参考第一节BeanFactory的实现

	public static void main(String[] args) {
        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("a023.xml");
        reader.loadBeanDefinitions(new FileSystemResource("src/main/resources/a023.xml"));
        for (String name : beanFactory.getBeanDefinitionNames()) {
            System.out.println(name);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值