您现在的位置是:首页 >技术教程 >Spring 容器概览网站首页技术教程

Spring 容器概览

CHENFU_JAVA 2024-06-21 12:01:02
简介Spring 容器概览

容器概览

容器概览 Spring 中的 Ioc 容器,我们可以大致上分为两种:

  • BeanFactory
  • ApplicationContext

BeanFactory

BeanFactory 是最最基础的 IoC 容器,它提供了一个 IoC 容器所需的基本功能。XmlBeanFactory 就是它的实现之一。

BeanFactory 默认采用延迟初始化策略,即当容器启动时,并未完成 Bean 的初始化,只有当调用到该 Bean 的实例时,才会完成其初始化操作,并进行依赖注入。

例如如下代码:

XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
User user = factory.getBean(User.class);

这样设计的好处是容器启动速度快,因为要做的事情比较少。

ApplicationContext

ApplicationContext 是在 BeanFactory 的基础上实现的,BeanFactory 的功能它都有,算是一种高级容器。
ApplicationContext 在 BeanFactory 的基础上提供了事件发布、国际化等功能。
同时,ApplicationContext 和 BeanFactory 还有一个很大的不同在于 ApplicationContext 在容器启动时,就会完成所有 Bean 的初始化,这也就以为着容器启动时间较长,并且对系统资源要求也较高。

例如如下一段代码:

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

BeanFactory

BeanFactory 的继承关系图非常大,可在 IDEA 中查看

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    @Nullable
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    @Nullable
    Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}

BeanFactory 主要提供了一些和 Bean 相关的查询方法。

属性 & 方法介绍

FACTORY_BEAN_PREFIX

这是定义的 FactoryBean 前缀

getBean

getBean 方法一共有五个。在获取一个 Bean 的时候,可以指定 Bean 的名字,也可以指定 Bean 的类型,也可以同时指定,这个好理解。还有两个重载的方法里边有一个 args 参数,args 是获取 Bean 时所需要的参数,如果使用该方法给 Bean 配置参数,需要将 Bean 的 scope 设置为 prototype,这就意味着每次获取 Bean 的时候,才去进行 Bean 的初始化(否则配置的参数无法生效)。

getBeanProvider

用于获取指定 Bean 的提供者,可以看到它返回的是一个 ObjectProvider,该类扩展自 ObjectFactory,从 Spring4.3 时开始提供。

ObjectFactory

该类定义如下

@FunctionalInterface
public interface ObjectFactory<T> {
    T getObject() throws BeansException;
}

ObjectFactory 有点类似于 FactoryBean。不同的是,ObjectFactory 中只有一个 getObject 方法,该方法可以返回 Object 实例。ObjectFactory 与 FactoryBean 相似,但是后者的实现通常是在 BeanFactory 中定义为 SPI 实例,而此类的实现通常是作为 API 注入给其他 Bean。

Java SPI(Service Provider Interface)机制

Java SPI(Service Provider Interface)机制是一种用于实现动态服务注册和发现的机制。它允许在运行时动态地添加、移除和服务化组件,从而提高了应用程序的灵活性和可扩展性。

Java SPI机制的核心是基于接口的注册和查找。当一个类实现了某个接口时,它可以将自己注册到相应的服务提供者中。服务提供者则负责维护所有已注册的实现类,并提供统一的访问点。

Java SPI机制通常用于框架和库的开发中,例如Spring框架中的BeanFactory和ApplicationContext接口就使用了SPI机制来管理Bean实例。通过SPI机制,我们可以在不修改原有代码的情况下,动态地添加或移除Bean实例,从而实现更加灵活的配置方式。

总之,Java SPI机制是一种非常强大的动态服务注册和发现机制,可以帮助我们更加方便地管理和使用各种组件和服务。

ObjectProvider

该类定义如下

public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
    //返回指定类型的 bean, 如果容器中不存在, 抛出 NoSuchBeanDefinitionException 异常;如果容器中有多个此类型的 bean, 抛出 NoUniqueBeanDefinitionException 异常
    T getObject(Object... args) throws BeansException;
    //如果指定类型的 bean 注册到容器中, 返回 bean 实例, 否则返回 null
    @Nullable
    T getIfAvailable() throws BeansException;
    //如果指定类型的 bean 在容器中只有一个 bean, 返回 bean 实例, 如果不存在则返回 null;如果容器中有多个此类型的 bean, 抛出 NoUniqueBeanDefinitionException 异常
    @Nullable
    T getIfUnique() throws BeansException;
    // Spring5.0 之后提供,返回指定类型 Bean 的迭代器
    @Override
    default Iterator<T> iterator() {
        return stream().iterator();
    }
    //转为 Stream
    default Stream<T> stream() {
        throw new UnsupportedOperationException("Multi element access not supported");
    }
    default Stream<T> orderedStream() {
        throw new UnsupportedOperationException("Ordered element access not supported");
    }
}

那么它有什么用呢?
从 Spring4.3 开始,在 xxxService 中注入 xxxDao 时,如果构造方法只有一个参数,可以不用添加 @Autowired 注解,但是如果 xxxDao 为 null,则会导致 xxxService 初始化失败,通过 ObjectProvider 可以解决:

@Service
public class UserService {
    private UserDao userDao;

    public UserService(ObjectProvider<UserDao> userDao) {
        this.userDao = userDao.getIfUnique();
    }

    @Override
    public String toString() {
        return "UserService{" +
                "userDao=" + userDao +
                '}';
    }
}

containsBean

判断容器中是否包含某个 Bean。

isSingleton

判断某个 Bean 是否是单例的。

isPrototype

判断某个 Bean 是否是 prototype。

isTypeMatch

返回指定名称的 Bean 是否匹配指定的类型。

getType

返回指定名称的 Bean 对应的数据类型。

getAliases

返回 Bean 的别名。

这就是 BeanFactory 中定义的所有方法,可以看到,基本上都是容器相关的查询方法,接下来将在 BeanFactory 的各种实现类中,对其进行实现。

二级接口

BeanFactory 作为 IoC 容器中最顶层的定义,没有继承任何接口,我们可以称之为一级接口,直接继承自 BeanFactory 的接口有三个,我们称之为二级接口。

HierarchicalBeanFactory

HierarchicalBeanFactory 继承自 BeanFactory,定义了工厂分层,在其基础上又扩展了两个方法:

public interface HierarchicalBeanFactory extends BeanFactory {
    BeanFactory getParentBeanFactory();
    boolean containsLocalBean(String name);
}
  • getParentBeanFactory 方法返回 Bean 工厂的父工厂,实现了工厂分层。
  • containsLocalBean 方法则判断本地工厂是否包含这个 Bean。

HierarchicalBeanFactory 有一个子接口 ConfigurableBeanFactory,ConfigurableBeanFactory 接口继承自 HierarchicalBeanFactory 和 SingletonBeanRegistry,其中 SingletonBeanRegistry 这个接口定义了对单例 Bean 的定义以及获取方法。也就是说,ConfigurableBeanFactory 中兼具工厂分层和单例处理功能。同时,在 HierarchicalBeanFactory 中 getParentBeanFactory 所 get 到的对象,也是在 ConfigurableBeanFactory 中完成配置。

AutowireCapableBeanFactory

AutowireCapableBeanFactory 继承自 BeanFacotory,它扩展了自动装配的功能。

public interface AutowireCapableBeanFactory extends BeanFactory {
    int AUTOWIRE_NO = 0;
    int AUTOWIRE_BY_NAME = 1;
    int AUTOWIRE_BY_TYPE = 2;
    int AUTOWIRE_CONSTRUCTOR = 3;
    @Deprecated
    int AUTOWIRE_AUTODETECT = 4;
    String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
    <T> T createBean(Class<T> beanClass) throws BeansException;
    Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
    void autowireBean(Object existingBean) throws BeansException;
    Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
    void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException;
    Object configureBean(Object existingBean, String beanName) throws BeansException;
    Object initializeBean(Object existingBean, String beanName) throws BeansException;
    void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;
    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
    void destroyBean(Object existingBean);
    <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
    Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;
    @Nullable
    Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;
    @Nullable
    Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;
}
  • 五个常量定义了五种不同的装配策略,分别是:不自动装配、通过名称自动装配、通过类型自动装配、通过构造方法自动装配,还有一个过期的常量。

  • ORIGINAL_INSTANCE_SUFFIX 则是初始化实例给定名称时约定的后缀,该后缀会添加到类的全路径后面,例如:com.mypackage.MyClass.ORIGINAL。

  • createBean 方法用来创建 Bean 实例;

  • autowire* 方法则用来完成自动装配;

  • configureBean 用来配置 Bean;

  • initializeBean 用来初始化 Bean;

  • applyBeanPropertyValues 将指定 bean 的 BeanDefinition 应用到一个已经存在的 Bean 上

  • applyBeanPostProcessorsBeforeInitialization/applyBeanPostProcessorsAfterInitialization 调用 Bean 的后置处理器;

  • destroyBean 方法用来销毁 Bean;

  • resolve* 方法用来解析 Bean。

ListableBeanFactory

ListableBeanFactory 继承自 BeanFacotory,该接口可以列出工厂可以生产的所有实例。

public interface ListableBeanFactory extends BeanFactory {
    boolean containsBeanDefinition(String beanName);
    int getBeanDefinitionCount();
    String[] getBeanDefinitionNames();
    String[] getBeanNamesForType(ResolvableType type);
    String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);
    String[] getBeanNamesForType(@Nullable Class<?> type);
    String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException;
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
    @Nullable
    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException;
}
  • containsBeanDefinition:判断容器是否包含某一个 Bean 的定义。
  • getBeanDefinitionCount:获取 BeanDefinition 数量。getBeanDefinitionCount 和
  • containsBeanDefinition 执行效率较低,慎用。
  • getBeanDefinitionNames:获取所有 Bean 的名字。
  • getBeanNamesForType:返回指定类型的 BeanName。
  • getBeansOfType:返回指定类的名称和 Bean Map(相同类型的 Bean 可能存在多种实例)。
  • getBeanNamesForAnnotation:根据注解获取指定的 BeanName。
  • getBeansWithAnnotation:根据注解获取指定的 BeanName 以及 Bean Map。
  • findAnnotationOnBean:根据指定 beanName 和注解类型查找指定的 Bean。

ListableBeanFactory 有一个实现接口 ConfigurableListableBeanFactory,这是以上所介绍接口的集大成者,ConfigurableListableBeanFactory 继承自 ListableBeanFactory、AutowireCapableBeanFactory 以及 ConfigurableBeanFactory,可以看到,三个二级接口功能集于一身,它包含了 BeanFactory 体系目前的所有方法。这些方法都在 DefaultListableBeanFactory 中进行实现。

引用

  1. Spring 源码系列之容器概览
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。