美文网首页
Spring IoC之原理解析(二)

Spring IoC之原理解析(二)

作者: 萌妈码码 | 来源:发表于2018-10-05 23:55 被阅读0次

    理解IoC前需要搞清楚

    • IoC容器基本接口BeanFactory和ApplicationContext
    • Bean对象在Spring实现中的描述BeanDefinition

    理解BeanFactory

    BeanFactory,生产Bean的工厂,负责生产和管理各个Bean实例。


    BeanFactory主要继承结构
    1. 最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。而ListableBeanFactory,可以获取多个Bean。
    2. HierarchicalBeanFactory,说明可以在应用中起多个 BeanFactory,然后可以将各个 BeanFactory 设置为父子关系。
    3. AutowireCapableBeanFactory是用来自动装配Bean用的。
    4. ConfigurableListableBeanFactory继承了第二层所有的三个接口。

    理解ApplicationContext

    ApplicationContext其实也是一个BeanFactory。


    ApplicationContext主要继承结构
    1. ApplicationContext 继承了 ListableBeanFactory和HierarchicalBeanFactory。实现类组合了AutowireCapableBeanFactory,从方法getAutowireCapableBeanFactory()可以看出。
    2. 三个常用的实现类:
    • ClassPathXmlApplicationContext 兜兜转转了好久才到 ApplicationContext 接口,顾名思义,XML配置文件是以ClassPath为相对路径的。
    • FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,其他和 ClassPathXmlApplicationContext 基本上一样。
    • AnnotationConfigApplicationContext 是基于注解来使用的,它不需要配置文件,采用 java 配置类和各种注解来配置,是比较简单的方式,也是大势所趋吧。
    BeanFactory和ApplicationContext的区别和联系

    ApplicationContext是Spring提供的一个高级IoC容器,它除了能够提供容器的基本功能之外,还为用户提供了以下附加服务:

    • 支持信息源,可以实现国际化。(继承MessageSource)
    • 访问资源。(继承ResourcePatternResolver)
    • 支持应用事件。(继承ApplicationEventPublisher)
    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
            MessageSource, ApplicationEventPublisher, ResourcePatternResolver 
    

    其实通过查看源码,在ApplicationContext的refresh()->refreshBeanFactory()方法中,可以看到

    DefaultListableBeanFactory beanFactory = createBeanFactory();
    

    ApplicationContext的getAutowireCapableBeanFactory()返回的也是这个DefaultListableBeanFactory。从BeanFactory继承体系可以看到,这个实现类基本是最牛的BeanFactory了。站在更高的层次看ApplicationContext,虽然它继承自BeanFactory,但是不应该把它理解成BeanFactory的实现或者扩展,而是说其内部持有一个BeanFactory(DefaultListableBeanFactory),所有的BeanFactory相关的操作其实都是委托给这个实例来处理。更像是静态代理。

    另外,BeanFactory和ApplicationContext都只是定义了IoC容器的基本行为,而不关心Bean是如何生产和加载的。要知道工厂是如何生产对象的,需要看具体的IoC容器的实现,Spring提供了很多IoC容器的实现,比如最基本的XmlBeanFactory, 高级点的ClasspathXmlApplicationContext等。

    理解BeanDefinition

    SpringIOC容器管理了我们定义的各种Bean对象及其相互的关系,Bean对象在Spring实现中是以BeanDefinition来描述的。
    BeanDefinition的接口定义及解析如下:

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    
       // 我们可以看到,默认只提供 sington 和 prototype 两种,
       // 很多读者可能知道还有 request, session, globalSession, application, websocket 这几种,
       // 不过,它们属于基于 web 的扩展。
       String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
       String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
    
       // 比较不重要,直接跳过吧
       int ROLE_APPLICATION = 0;
       int ROLE_SUPPORT = 1;
       int ROLE_INFRASTRUCTURE = 2;
    
       // 设置父 Bean,这里涉及到 bean 继承,不是 java 继承。请参见附录的详细介绍
       // 一句话就是:继承父 Bean 的配置信息而已
       void setParentName(String parentName);
    
       // 获取父 Bean
       String getParentName();
    
       // 设置 Bean 的类名称,将来是要通过反射来生成实例的
       void setBeanClassName(String beanClassName);
    
       // 获取 Bean 的类名称
       String getBeanClassName();
    
    
       // 设置 bean 的 scope
       void setScope(String scope);
    
       String getScope();
    
       // 设置是否懒加载
       void setLazyInit(boolean lazyInit);
    
       boolean isLazyInit();
    
       // 设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),
       // 是 depends-on="" 属性设置的值。
       void setDependsOn(String... dependsOn);
    
       // 返回该 Bean 的所有依赖
       String[] getDependsOn();
    
       // 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
       // 如果根据名称注入,即使这边设置了 false,也是可以的
       void setAutowireCandidate(boolean autowireCandidate);
    
       // 该 Bean 是否可以注入到其他 Bean 中
       boolean isAutowireCandidate();
    
       // 主要的。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
       void setPrimary(boolean primary);
    
       // 是否是 primary 的
       boolean isPrimary();
    
       // 如果该 Bean 采用工厂方法生成,指定工厂名称。对工厂不熟悉的读者,请参加附录
       // 一句话就是:有些实例不是用反射生成的,而是用工厂模式生成的
       void setFactoryBeanName(String factoryBeanName);
       // 获取工厂名称
       String getFactoryBeanName();
       // 指定工厂类中的 工厂方法名称
       void setFactoryMethodName(String factoryMethodName);
       // 获取工厂类中的 工厂方法名称
       String getFactoryMethodName();
    
       // 构造器参数
       ConstructorArgumentValues getConstructorArgumentValues();
    
       // Bean 中的属性值,后面给 bean 注入属性值的时候会说到
       MutablePropertyValues getPropertyValues();
    
       // 是否 singleton
       boolean isSingleton();
    
       // 是否 prototype
       boolean isPrototype();
    
       // 如果这个 Bean 是被设置为 abstract,那么不能实例化,
       // 常用于作为 父bean 用于继承,其实也很少用......
       boolean isAbstract();
    
       int getRole();
       String getDescription();
       String getResourceDescription();
       BeanDefinition getOriginatingBeanDefinition();
    }
    

    总结下,主要的信息包括Bean的名称,类型,Scope,父Bean的信息,是否懒加载,是不是Primary的Bean,是否可以自动注入到其他bean中,它依赖的Beans,如果该Bean采用工厂方法生成,那么制定工厂名称及工厂方法名称等,其属性值等。

    BeanDefinition继承体系

    理解了BeanFactory, ApplicationContext, BeanDefinition之后,就可以继续深入源码了解容器是怎么初始化的,bean是怎么创建及初始化等主题了。

    引用
    Spring IOC源码解读
    Spring IOC 容器源码分析

    相关文章

      网友评论

          本文标题:Spring IoC之原理解析(二)

          本文链接:https://www.haomeiwen.com/subject/qorcaftx.html