> 文章列表 > 02.容器实现BeanFactory和ApplicationContext实现

02.容器实现BeanFactory和ApplicationContext实现

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();// 注册BeanDefinitionbeanFactory.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 还不会解析 ${ } 与 #{ }*/}@Configurationstatic class Config {@Beanpublic Bean1 getBean1() {return new Bean1();}@Beanpublic Bean2 getBean2() {return new Bean2();}}static class Bean1 {public Bean1() {log.debug("构造 Bean1()");}@Autowiredprivate 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);});}@Configurationstatic class Config {@Beanpublic Bean1 bean1() {return new Bean1();}@Beanpublic Bean2 bean2() {return new Bean2();}@Beanpublic Bean3 bean3() {return new Bean3();}@Beanpublic 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()");}@Autowiredprivate 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;}}@Configurationstatic class Config {@Beanpublic Bean1 bean1() {return new Bean1();}@Beanpublic Bean2 bean2() {return new Bean2();}}@Configurationstatic class WebConfig {@Beanpublic ServletWebServerFactory servletWebServerFactory() {// 初始化一个内嵌的tomcatreturn new TomcatServletWebServerFactory();}@Beanpublic DispatcherServlet dispatcherServlet() {// 转发请求至对应的servletreturn new DispatcherServlet();}@Beanpublic DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {// 将请求转发器关联到tomcat容器return new DispatcherServletRegistrationBean(dispatcherServlet, "/");}@Bean("/hello")public Controller controller1() {// spring约定如果Bean的名字/开头则是一个servletreturn (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);}}