【Spring学习-2-2】底层架构核心概念-BeanFactory

一、BeanFactory理解

BeanFactory表示Bean工厂,所以很明显,BeanFactory会负责创建Bean,并且提供获取Bean的 API。 而ApplicationContext是BeanFactory的一种,在Spring源码中,是这么定义的:

public interface ApplicationContext extends 
        EnvironmentCapable, ListableBeanFactory, 
        HierarchicalBeanFactory, MessageSource,
        ApplicationEventPublisher, ResourcePatternResolver {
    ...
}

首先,在Java中,接口是可以多继承的,我们发现(结合下面的图面再看这段话会更加清晰):

  • ApplicationContext继承了 ListableBeanFactory 和 HierarchicalBeanFactory,而 ListableBeanFactory 和 HierarchicalBeanFactory 都继承至 BeanFactory,所以我们可以认为ApplicationContext继承了BeanFactory,相当于苹果继承水果, 宝马继承汽车一样,ApplicationContext也是BeanFactory的一种,拥有BeanFactory支持的所有功能。

  • 不过ApplicationContext比BeanFactory更加强大,ApplicationContext还基础了其他接口,也就表示ApplicationContext还拥有其他功能,比如MessageSource表示国际化,ApplicationEventPublisher表示事件发布,EnvironmentCapable表示获取环境变量,等等,关于 ApplicationContext后面再详细讨论。

  • 在Spring的源码实现中,当我们new一个ApplicationContext时,其底层会new一个BeanFactory出来。当使用ApplicationContext的某些方法时,比如getBean(),底层调用的是BeanFactory的 getBean()方法。

一、BeanFactory的一个重要实现类DefaultListableBeanFactory

  • BeanFactory接口存在一个非常重要的实现类是: DefaultListableBeanFactory,也是非常核心的。在关于Spring的其他文章中会更深入的理解。
  • 所以,我们可以直接来使用DefaultListableBeanFactory,而不用使用ApplicationContext的某个实现类,比如:
    /**
     * 直接来使用DefaultListableBeanFactory,而不用使用ApplicationContext的某个实现类
     */
    private static void test5() {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(TestService.class);
        beanFactory.registerBeanDefinition("testService", beanDefinition);
        System.out.println(beanFactory.getBean("testService"));

    }

file

DefaultListableBeanFactory实现了很多接口,表示它拥有很多功能:

类或接口 规范或实现
AliasRegistry 支持别名功能,一个名字可以对应多个别名
BeanDefinitionRegistry 可以注册、保存、移除、获取某个BeanDefinition
BeanFactory Bean工厂,可以根据某个bean的名字、或类型、或别名获取某个Bean对象
SingletonBeanRegistry 可以直接注册、获取某个单例Bean
SimpleAliasRegistry 它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名功能
ListableBeanFactory 在BeanFactory的基础上,增加了其他功能,可以获取所有 BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类 型获取{类型:对应的Bean}的映射关系
HierarchicalBeanFactory 在BeanFactory的基础上,添加了获取父BeanFactory的功能
DefaultSingletonBeanRegistry 它是一个类,实现了SingletonBeanRegistry接口,拥有了直 接注册、获取某个单例Bean的功能
ConfigurableBeanFactory 在HierarchicalBeanFactory和SingletonBeanRegistry的基础上, 添加了设置父BeanFactory、类加载器(表示可以指定某个类加载器进行类的加载)、设置 Spring EL表达式解析器(表示该BeanFactory可以解析EL表达式)、设置类型转化服务(表示 该BeanFactory可以进行类型转化)、可以添加BeanPostProcessor(表示该BeanFactory支持 Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能
FactoryBeanRegistrySupport 支持了FactoryBean的功能 11. AutowireCapableBeanFactory:是直接继承了BeanFactory,在BeanFactory的基础上,支持 在创建Bean的过程中能对Bean进行自动装配
AbstractBeanFactory
ConfigurableListableBeanFactory
AbstractAutowireCapableBeanFactory
DefaultListableBeanFactory
  1. ****:
  2. ****:实现了ConfigurableBeanFactory接口,继承了 FactoryBeanRegistrySupport,这个BeanFactory的功能已经很全面了,但是不能自动装配和 获取beanNames
  3. ****:继承了ListableBeanFactory、 AutowireCapableBeanFactory、ConfigurableBeanFactory
  4. ****:继承了AbstractBeanFactory,实现了 AutowireCapableBeanFactory,拥有了自动装配的功能
  5. ****:继承了AbstractAutowireCapableBeanFactory,实现了 ConfigurableListableBeanFactory接口和BeanDefinitionRegistry接口,所以 DefaultListableBeanFactory的功能很强大

一、BeanDefinition含义(理解描述)

BeanDefinition表示Spring容器中Bean的定义,在BeanDefinition类中存在很多属性用来描述一个Bean的定义。
注释:Spring容器中Bean的定义,就是通过xml配置、扫描注解把需要纳入到Spring容器中的类,通过BeanDefinition来定义。

二、BeanDefinition类中属性:

beanClass,表示Bean类型
scope,表示Bean作用域,单例或原型等
lazyInit:表示Bean是否是懒加载
initMethodName:表示Bean初始化时要执行的方法
destroyMethodName:表示Bean销毁时要执行的方法
等等...

基于以上内容,我们可以理解为BeanDefinition对象就是一个Bean的元数据,为什么Bean的元数据需要一个BeanDefinition来存储元数据呢?
因为一个被Spring容器管理的Bean不仅仅是放到Spring容器中,而是要应对不同场景,比如有单例和多例的Bean,有的Bean需要懒加载,有的Bean在被注入的时候需要执行初始化方法等等,而这些都需要额外来记录,单单靠Bean对象所对应的类自己是不行的,Bean对象所对应的类也就是Java类,他是相对于Spring更底层的东西,属于Jvm层,而Bean是属于Spring体系,Spring体系就需要想办法来记录这个Bean的信息,所以需要BeanDefinition对象保存Bean的元数据。

三、定义Bean的方式

3.1 声明式定义Bean

xml配置【<bean/>】
[email protected]
[email protected](@Service,@Controller)】

3.2 编程式定义Bean

基础代码:

Config.java

package cn.edkso.coreConcept;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("cn.edkso.coreConcept")
public class Config {
}

TestService.java

package cn.edkso.coreConcept;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

[email protected]
[email protected]
@Service
public class TestService {

    public TestService() {
        System.out.println("TestService被创建了!");
    }

    public void init(){
        System.out.println("TestService执行初始化方法!");
    }
}

编程式定义Bean代码:

    /**
     * 编程式定义BeanDefinition
     */
    private static void test1(){

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
        beanDefinition.setBeanClass(TestService.class);
        beanDefinition.setScope("prototype");
//        beanDefinition.setScope("singleton");
        beanDefinition.setLazyInit(false);
        beanDefinition.setInitMethodName("init");

        context.registerBeanDefinition("testService", beanDefinition);

        System.out.println(context.getBean("testService"));
        System.out.println(context.getBean("testService"));
    }

注释:编程式方式定义的Bean方式和声明式方式所定义的Bean,最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中。

四、BeanDefinition读取器

在Spring源码中提供了几种BeanDefinition读取器 (BeanDefinitionReader),这些BeanDefinitionReader在我们使用Spring时用得少,但在Spring 源码中用得多,相当于Spring源码的基础设施。

4.1 AnnotatedBeanDefinitionReader

    /**
     * AnnotatedBeanDefinitionReader   Bean读取器
     * -- 1.通过该Bean读取器,可以把一个类直接读取成BeanDefinition并进行注册;
     *      在读取过程中,会检测指定类中的各种注解,并根据注解做相应的处理。
     * -- 3.new AnnotationConfigApplicationContext(Config.class)
     *      内部源码就是通过AnnotatedBeanDefinitionReader读取的Config配置类
     */
    private static void test2(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

        AnnotatedBeanDefinitionReader abd = new AnnotatedBeanDefinitionReader(context);
        abd.register(TestService.class);

        System.out.println(context.getBean("testService"));
    }

4.2 XmlBeanDefinitionReader

xml配置Bean文件:
spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="testService" class="cn.edkso.coreConcept.TestService"></bean>

</beans>

XmlBeanDefinitionReader Bean读取器:

    /**
     * XmlBeanDefinitionReader  Bean读取器
     * -- 1.在xml文件中配置的bean可以通过此读取器读取,并进行注册。
     * -- 2.在早期Spring版本中,大多数都是通过xml来配置Bean,这样做的缺点是配置文件太多,并且耦合度高
     */
    private static void test3(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

        XmlBeanDefinitionReader xbd = new XmlBeanDefinitionReader(context);
        xbd.loadBeanDefinitions("spring.xml");

        System.out.println(context.getBean("testService"));
    }

4.3 ClassPathBeanDefinitionScanner

    /**
     * ClassPathBeanDefinitionScanner  Bean读取器(扫描器)
     * -- 1.扫描Bean读取器,会扫描指定包路径下的Bean进行读取,并进行注册。
     * -- 2.在指定包下,[email protected]@[email protected] 等注解的才是要纳入Spring进行管理的Bean
     */
    private static void test4(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

        ClassPathBeanDefinitionScanner cpbd = new ClassPathBeanDefinitionScanner(context);
        cpbd.scan("cn.edkso.coreConcept");

        System.out.println(context.getBean("testService"));
    }

版权声明:
作者:十下
链接:http://blog.edkso.cn/?p=1042
来源:十下博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
< <上一篇
下一篇>>
文章目录
关闭
目 录