Spring5 底层原理 BeanFactory常见实现(黑马)

BeanFactory

我们来用 BeanFactory 的子实现类 DefaultListableBeanFactory 基本的就可以对bean进行一些定义也就是将bean加入bean工厂;

下面代码是一个简单的Bean注册,但是Bean1中自动装配了Bean2:

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

这里就是一个简单的Bean定义(Config.class)并注册到了BeanFactory:

 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 的定义(class,scope,初始化)

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

打印一下结果看看:
在这里插入图片描述
发现我们确实把Config.class注册进去了,我们获得的是BeanName所以未我们设置的config,当然也可以设置其他。

这里发现注册进去的只有外部的一个类,内部的Bean1、Bean2并没有注入到BeanFacotry中。
也就是说@Configuration、@Bean没有识别到,或者说原本的BeanFactory的子实现类中缺少实现对这几个注解解析的能力,功能不是其提供的。

AnnotationConfigUtils

我们需要这个工具类用于注册一些后处理器,让功能完整。

  // 给BeanFactory添加一些常用的后处理器(用于解析注解 但是现在还没有调用,只是注册了这些后处理器)
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

注册之后我们再次打印一下 beanFactory中注册了的Bean:

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

结果除了我们自己注册的config,多了几个:
在这里插入图片描述
这几个的用途就在于完善一些BeanFactory的一些注解的识别,自动装配的实现等功能,我们继续往下。

internalConfigurationAnnotationProcessor: 解析@Configuration注解 以及里面的@Bean等注解
internalAutowiredAnnotationProcessor:解析@Autowired自动装配注解
internalCommonAnnotationProcessor:解析@Resource注解
internalEventListenerProcessor:
internalEventListenerFactory:

// 给BeanFactory 添加一些常用的后处理器 我们根据类型(getBeansOfType)获取后处理器
        // 类型为 BeanFactoryPostProcessor.class
        // 使用 internalConfigurationAnnotationProcessor 后处理器 解析注解 将两个 Bean注入
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(BeanFactoryPostProcessor -> {
            BeanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

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

通过运行后处理器在打印查看结果可以发现bean1、bean2 也注册进去了:
在这里插入图片描述
我也可以看一下我们获得的后处理器名字和后处理器实例:

  Map<String, BeanFactoryPostProcessor> beans = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
        beans.forEach((k, v) -> System.out.println(k + "====" + v));

结果和上面对比可以发现两个后处理器就是上面其中俩:
在这里插入图片描述

后面的@Autowired不生效也是一样配置,只是类型不一样:前面的是对BeanFactory的,这个是对于Bean的;

配置后处理器前:

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

结果为: null 说明没有注入进去;

配置后处理器后:

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

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

结果正常 :
在这里插入图片描述

在这个子实现类中Bean的实例化是在调用时才进行实例化,也就是懒汉(下面代码可以变为恶汉式):

// 这个方法可以让单例的bean提前实例化 而不是默认的 在用到的时候在实例化
       beanFactory.preInstantiateSingletons();

后处理的排序

当出现这个的时候是执行哪个呢?

  	@Resource
 	@Autowired
    private Bean2 bean2;

答案是 @Autowired,原因是在后处理器Map中@Autowired更靠前,其原因是在后处理器中维护着一个值,用来保持一个顺序,靠前的就先调用。
如果需要也可以进行调整。
其中维护的值如下图所示类似:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aholic 冲冲冲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值