History Of Dependency Lookup

Dependency lookup:→ DI → 依赖查找
Spring的很多技术实际上是来源于JavaEE J2SE JNDI里的相关实现

  • 单一类型依赖查找 Singleton Lookup
    • JNDI:javax.naming.Context #lookup(javax.naming.Name)
    • Java Beans:java.beans.beancontext.BeanContext
  • 集合类型依赖查找 List Lookup
    • Java Beans:java.beans.beancontext.BeanContext
  • 层次性依赖查找 Hierarchical Lookup
    • Java Beans:java.beans.beancontext.BeanContext

Spring对于依赖查找的实现会比JNDIJavaEE更加优雅简洁,这也是使用Spring的一个原因

Singleton Lookup

单一类型依赖查找接口:BeanFactory

  • 根据Bean名称查找
    public interface BeanFactory {
         /**
         * 最常用的获取Bean接口
         * 可根据Bean名称,实时查找一个Bean
         */
         Object getBean(String name) throws BeansException;
    
         /**
         * 可在实时查找Bean时,覆盖Bean的构造器参数,以此来获得参数自定义的Bean
         * Bean的作用域(scope)为原型(property)时使用,可在每次调用时动态调整参数
         * Bean的作用域(scope)为单例(singleton)时使用,非常危险,每次调用同一个对象都会变动
         * 
         * @since 2.5 Spring 2.5引入
         */
         Object getBean(String name, Object... args) throws BeansException;
    }
    
  • 根据Bean类型查找
    • 实时查找
    • 延迟查找
    public interface BeanFactory {
         /**
         * 根据Bean的Class类型,实时查找一个Bean
         * 
         * @since 3.0 Spring 3.0引入
         */
        <T> T getBean(Class<T> requiredType) throws BeansException;
    
         /**
         * 根据Bean的Class类型,延迟查找一个Bean,
         * 并在查找过程中,覆盖Bean构造器参数,不推荐使用
         * 
         * @since 4.1 Spring 4.1引入
         */
        <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    
         //-------------以上为按类型实时查找,以下为按类型延迟查找----------
    
         /**
         * 根据Bean的Class类型,延迟查找一个Bean
         * 
         * @since 5.1
         */
        <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
         /**
         * 根据Bean的ResolvableType类型,延迟查找一个Bean,
         * 
         * @since 5.1
         */
        <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
    }
    

延迟查找

延迟查找在getBean时,会先返回一个ObjectProvider,而ObjectProviderObjectFactory的子类,通过调用ObjectFactory#getObject方法获得Bean,这种通过二次查找,先拿到一个类似句柄的东西,通过句柄查找Bean的方式,就是延迟查找。

更多链接BeanFactoryObjectFactory的区别(待补充)

ResolvableType

ResolvableType是因为JDK5引入了泛型后,为处理泛型类型的查找而引入的新的类型概念

  • 根据Bean名称+类型查找
    public interface BeanFactory {
         /**
         * 根据Bean的名称与Class类型,实时查找一个Bean
         * 
         */
     	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
    }
    

List Lookup

List Lookup:集合查找
集合类型依赖查找接口:ListableBeanFactory
ApplicationContext一样,继承了BeanFactory,通过调用#getBeanFactory再调用对应方法的方式,去实现单一Bean的查找

返回的集合不限于List,而是Map+Collection

  • 通过Bean类型查找
    • 获取同类型Bean的名称列表
    • 获取同类型Bean的实例列表
    public interface ListableBeanFactory extends BeanFactory {
        //--------获取同类型Bean的名称列表---------
    
        /**
        * 根据给定的Class类型,返回Bean的名称列表
        */
        String[] getBeanNamesForType(@Nullable Class<?> type);
        /**
        * 根据给定的ResolvableType类型,返回Bean的名称列表
        */
        String[] getBeanNamesForType(ResolvableType type);
    
        //--------获取同类型Bean的名称列表---------
    
        /**
        * 根据给定的ResolvableType类型,返回Bean的实例列表
        */
        <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;
        /**
        * 根据给定的ResolvableType类型,返回Bean的实例列表
        * @param type 指定的Bean Class类型
        * @param includeNonSingletons 查找时是否包含非单例的,使用#getBeansOfType时为true
        * @param allowEagerInit 是否初始化FactoryBean中的实例,使用#getBeansOfType时为true
        */
        <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
      		throws BeansException;
    }
    
  • Spring3增加 - 通过注解类型查找
    • 获取标注类型Bean的名称列表
    • 获取标注类型Bean的实例列表
    • 获取指定名称 + 标注类型Bean实例
    public interface ListableBeanFactory extends BeanFactory {
        /**
        * 根据注解类型,返回带有该注解的Bean名称列表
        * 
        * @since 4.0
        */
        String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
    
        /**
        * 根据注解类型,返回带有该注解的Bean实例列表
        * 是否想起了Aop根据是否带有注解来控制是否进行切面的功能
        * 
        * @since 3.0
        */
        Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
    
        /**
        * 根据Bean名称 + 注解类型,返回一个Bean实例列表
        * 实际为上面两个功能的结合使用,源码中的@see文档注释也说明了这一点
        * 
        * @since 3.0
        * @see #getBeanNamesForAnnotation 
        * @see #getBeansWithAnnotation 
        */
        <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
      		throws NoSuchBeanDefinitionException;
    }
    

Bean的名称和Bean的列表,谁重要?

调用#getBeans相关的接口,会触发Bean的初始化,容易出现各种未知的错误

Hierarchical Lookup

Hierarchical Lookup:层次性查找
层次性依赖查找接口:HierarchicalBeanFactoryBeanFactoryUtils
HierarchicalBeanFactory负责定义层次性,BeanFactoryUtils负责提供辅助功能

应用程序可能会存在多个容器,当想要多个容器之间联合工作时,就需要用到层次性查找功能 - 将容器组合为父子容器

Spring的层次性查找,只会记录父容器,没有直接指向子容器的方法,采用的是类似于双亲委派的方式。
Spring会先查找子容器,再查找父容器,不同的是,父子容器都有的BeanDefinition,会优先取子容器的BeanDefinition

  • 查找双亲BeanFactory:#getParentBeanFactory
    public interface HierarchicalBeanFactory extends BeanFactory {
    
        /**
        * 返回父容器,为空时说明已经是最顶层的容器
        */
        BeanFactory getParentBeanFactory();
    }
    
  • 根据Bean名称查找
    public interface HierarchicalBeanFactory extends BeanFactory {
    
        /**
        * 判断是否存在Bean,只判断当前容器内的Bean
        *  
        * @param name Bean的名称
        */
        boolean containsLocalBean(String name);
    }
    
    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
        // 对应的子类方法实现
        @Override
        public boolean containsLocalBean(String name) {
            //先将别名处理为真正的Bean名称,里面有一段代码很有趣
            String beanName = transformedBeanName(name);
            //再逐个判断当前容器中的各个部分是否含有Bean
            return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) && (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName)));
        }
        //继续往下找
        protected String transformedBeanName(String name) {
            return canonicalName(BeanFactoryUtils.transformedBeanName(name));
        }
    
        //此时已经位于org.springframework.core.SimpleAliasRegistry#canonicalName
        public String canonicalName(String name) {
            String canonicalName = name;
            String resolvedName;
            //可能在通过别名的map找到一个名称时,这个名称依然是别名
            //所以需要不断的循环,直到通过name找不到时才算真正的找到
            //也就反向说明了,bean可以有多个别名
            do {
                resolvedName = this.aliasMap.get(canonicalName);
                    if (resolvedName != null) {
                        canonicalName = resolvedName;
                    }
            }
            while (resolvedName != null);
            return canonicalName;
        }
    }
    
  • 根据Bean类型查找实例列表
    • 单一类型
    • 集合类型
    public abstract class BeanFactoryUtils {
        //------------单一类型----------
    
        /**
        * 根据类型,从指定工厂中获取一个Bean
        * 从实现上也可以看出,其实就是调用的ListableBeanFactory#getBeansOfType方法
        * 
        * @param lbf 可列举的Bean工厂
        * @param Class<T> Bean的Class类型
        */
        public static <T> T beanOfType(ListableBeanFactory lbf, Class<T> type) throws BeansException {
            Assert.notNull(lbf, "ListableBeanFactory must not be null");
            Map<String, T> beansOfType = lbf.getBeansOfType(type);
            return uniqueBean(type, beansOfType);
        }
    
        /**
        * 根据类型以及其他定义参数,从指定工厂中获取一个Bean
        * 
        * @param type 指定的Bean Class类型
        * @param includeNonSingletons 查找时是否包含非单例的,使用#getBeansOfType时为true
        * @param allowEagerInit 是否初始化FactoryBean中的实例,使用#getBeansOfType时为true
        */
        public static <T> T beanOfType(ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
            Assert.notNull(lbf, "ListableBeanFactory must not be null");
            Map<String, T> beansOfType = lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit);
            return uniqueBean(type, beansOfType);
        }
    
        //------------集合类型----------
    
        /**
        * 判断是否存在Bean,会判断当前容器与父容器
        * 
        * @param name Bean的名称
        */
        public static <T> T beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)throws BeansException {
            Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type);
            return uniqueBean(type, beansOfType);
        }
    
        /**
        * 找一个参数少的经典的例子来仔细看
        * 
        * @param lbf 需要拿值的容器
        * @param Class<T> Bean的Class类型
        */
        public static <T> Map<String, T> beansOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type) throws BeansException {
            Assert.notNull(lbf, "ListableBeanFactory must not be null");
            //初始化最终返回的Bean Map
            Map<String, T> result = new LinkedHashMap<>(4);
            //先将子容器内,属于该类型的Bean放入总结果集的Map中
            //因为下面有递归调用,经过下面的操作,有可能含有父集的Bean,所以是总结果集
            result.putAll(lbf.getBeansOfType(type));
            //如果该容器可以分级查找
            if (lbf instanceof HierarchicalBeanFactory) {
                HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
                //如果该容器含有父容器并且父容器是可列举的,instanceof碰到null不会空指针,而是判定为false
                if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
                    //递归调用,对父容器使用同样的方法查找Bean,并获得Bean的返回Map parentResult 
                    Map<String, T> parentResult = beansOfTypeIncludingAncestors(
                        (ListableBeanFactory) hbf.getParentBeanFactory(), type);
                    //遍历父容器,当总结果集内不存在该Bean,并且当前容器内也不存在这个Bean时,将Bean加入总结果集中
                    //这里是根据Bean名称判断,而不是根据实例化的Bean,根据Bean的实例判断,会提前触发Bean的初始化,会产生很多未知的影响
                    //由此也可以看出,Bean是可以被覆盖的,子容器覆盖父容器相同Bean名称的Bean
                    parentResult.forEach((beanName, beanInstance) -> {
                        if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
                            result.put(beanName, beanInstance);
                        }
                    });
                }
            }
            //返回总的结果集
            return result;
        }
        /**
        * 判断是否存在Bean,会判断当前容器与父容器
        * 
        * @param lbf 需要拿值的容器
        * @param Class<T> Bean的Class类型
        * @param includeNonSingletons 查找时是否包含非单例的,使用#getBeansOfType时为true
        * @param allowEagerInit 是否初始化FactoryBean中的实例,使用#getBeansOfType时为true
        */
        public static <T> T beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
            Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type, includeNonSingletons, allowEagerInit);
            return uniqueBean(type, beansOfType);
        }
    
    }
    

BeanFactoryUtils# beansOfTypeIncludingAncestors方法可以看出,Bean的层级查找很像双亲委派原则,但是父子层级的选择优先级上又不同,双亲委派是优先取父容器内的对象,而Spring则是优先取子容器里的对象。

出现区别的原因主要还是因为两者的定位不同
JDK需要保证同一个类在不同地方对其的引用也是相同的,这样程序的类对象才能统一。
而Spring容器则是面向应用的,子应用很多时候需要对父应用的功能进行扩展,所以就得保证获得的Bean是自己自定义的,就和重写方法的调用原则很相似。

  • 根据Java注解查找名称列表
    public abstract class BeanFactoryUtils {
    
        /**
        * 根据特定条件,从指定容器中拿到Bean的名称列表
        * 和上面的方法过程很类似,就不详细说了
        * 
        * @param lbf 需要拿值的容器
        * @param Class<T> Bean的Class类型
        * @param includeNonSingletons 查找时是否包含非单例的,使用#getBeansOfType时为true
        * @param allowEagerInit 是否初始化FactoryBean中的实例,使用#getBeansOfType时为true
        * @since 5.0
        * @see ListableBeanFactory#getBeanNamesForAnnotation(Class)
        */
        public static String[] beanNamesForAnnotationIncludingAncestors(ListableBeanFactory lbf, Class<? extends Annotation> annotationType) {
            Assert.notNull(lbf, "ListableBeanFactory must not be null");
            String[] result = lbf.getBeanNamesForAnnotation(annotationType);
            if (lbf instanceof HierarchicalBeanFactory) {
                HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
                if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
                    String[] parentResult = beanNamesForAnnotationIncludingAncestors(
                    (ListableBeanFactory) hbf.getParentBeanFactory(), annotationType);
                    result = mergeNamesWithParent(result, parentResult, hbf);
                }
            }
            return result;
        }
    }
    

HierarchicalBeanFactory 中,只有获取方法,没有设置方法,这是为什么呢?

我们来看下HierarchicalBeanFactory的子接口ConfigurableBeanFactory

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
    /**
    * 子接口ConfigurableBeanFactory
    * 不仅继承了HierarchicalBeanFactory还继承了SingletonBeanRegistry
    * 实际上是为了对设置方法的统一
    * SingletonBeanRegistry → 单例bean的注册中心
    * 从名称上也可以感受到 Configurable → 可配置的,就是将需要配置的东西抽离了出来
    * 
    * @param parentBeanFactory 父容器
    */
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
}

Lazy Lookup

Lazy Lookup:延迟查找
延迟查找类似于获取一个句柄,当句柄指向的Bean改变时,引用者不需要有其他操作
延迟加载类ObjectFactoryObjectProvider不一定只含有一个Bean(虽然有的API只返回一个),有单独Bean的查找接口,也有Stream流形式的API提供查找或者处理功能。
在容器初始化阶段,有些Bean会在第一次加载时因为各种原因没有被完全加载(例如循环依赖),会将Bean在另一个阶段进行完全加载,这种方式就很像ObjectFactory的延迟加载
延迟查找接口:ObjectFactoryObjectProvider
基础用法可参考Spring - Bean Definition - Base中的延迟初始化一节
以下为扩展的使用接口

/**
* @since 1.0.2
*/
public interface ObjectFactory<T> {
    /**
    * 返回这个工厂管理的一个单例或者原型的实例
    */
    T getObject() throws BeansException;
}

/**
* @since 4.3
*/
public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
    /**
    * 继承的父类的方法,返回一个管理的实例
    */
    T getObject(Object... args) throws BeansException;

    /**
    * 如果有的情况下返回一个对应的实例
    */
    T getIfAvailable() throws BeansException;

    /**
    * 使用Lamdba对方法进行增强,没有Bean时可以返回一个自己控制的默认值
    */
    default T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException {
        T dependency = getIfAvailable();
        return (dependency != null ? dependency : defaultSupplier.get());
    }

    /**
    * 使用Lamdba对方法进行增强,如果有Bean时,可以对Bean进行消费
    */
    default void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException {
        T dependency = getIfAvailable();
        if (dependency != null) {
            dependencyConsumer.accept(dependency);
        }
    }

    /**
    * 增加的Lamdba流式操作,可以对方法进行增强,如果有Bean时,可以对Bean进行消费
    * 子类DefaultListableBeanFactory 对其进行了实现
    */
    default Stream<T> stream() {
        throw new UnsupportedOperationException("Multi element access not supported");
    }
}

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    /**
    * 对ObjectProvider stream方法的实现,使其可以进行流式操作
    */
    public Stream<Object> stream() {
        return this.resolveStream(false);
    }
}

方法使用示例

public class ObjectProviderDemo {

    @Bean//方法名就是Bean名
    public String helloWorld() {
        return "Hello,World";
    }

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 将类 ObjectProviderDemo 注册为配置类(Configuration Class)
        applicationContext.register(ObjectProviderDemo.class);
        // 启动应用上下文
        applicationContext.refresh();
        // 依赖查找集合对象
        lookupByObjectProvider(applicationContext);
        lookupIfAvailable(applicationContext);
        lookupByStreamOps(applicationContext);

        // 关闭应用上下文
        applicationContext.close();

    }

    //流式操作
    private static void lookupByStreamOps(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
        objectProvider.stream().forEach(System.out::println);
    }

    //含有默认值的查找
    private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
        User user = userObjectProvider.getIfAvailable(User::createUser);
        System.out.println("当前 User 对象:" + user);
    }

    //直接进行延迟依赖查找
    private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
        ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
        System.out.println(objectProvider.getObject());
    }
}

Dependency lookup safely

此处讨论的安全性是指查找Bean时是否会抛出异常
依赖查找安全性对比

依赖查找类型 代表实现 是否安全
单一类型查找 BeanFactory#getBean
ObjectFactory#getObject
ObjectProvider#getIfAvailable
集合类型查找 ListBeanFactory#getBean
ObjectProvider#stream

当进行层次性查找时,安全性依赖于使用的BeanFactory

Built-in dependencies

Built-in dependencies:内建依赖

tip Spring容器在启动时,会自动注入一些依赖,以供容器运行使用
AbstarctApplicationContext:是ApplicationContext的实现基类,定义了大量的容器上下文功能的基础实现。
此类的实现功能中,包括但不限于AnnotationConfigurationApplicationContextWeb支持,,所以会初始化相关的一些依赖

AbstarctApplicationContext内建的依赖

Bean名称 Bean实例 使用场景
environment Environment对象 外部化配置以及Profiles
systemProperties java.util.Propertie对象 Java系统属性
systemEnvironment java.util.Map对象 操作系统环境变量
messageSource MessageSource对象 国际化文案
lifecycleProcessor LifecycleProcessor对象 Lifecycle Bean处理器
applicationEventMulitcaster ApplicationEventMulitcaster对象 spring事件广播

注解驱动下内建的依赖,使用xml或者注解的component-scan,或者显示使用ApplicationContext激活时,会内建以下依赖

Bean名称 Bean实例 使用场景
org.springframework.context.annotation. internalConfigurationAnnotationProcessor ConfigurationClassPostProcessor对象 处理Spring配置类,控制BeanFactory的生命周期
org.springframework.context.annotation. internalAutowiredAnnotationProcessor AutowiredAnnotationBeanPostProcessor对象 处理@Autowired以及@Value注解
org.springframework.context.annotation. internalCommonAnnotationProcessor对象 CommonAnnotationBeanPostProcessor 满足一定情况下,激活jsr-250注解,如:@PostConstruct
org.springframework.context.event. internalEventListenerProcessor EventListenerMethodProcessor对象 处理标记@EventListener的Spring事件监听方法
org.springframework.context.event. internalEventListenerFactory DefaultEventListenerFactory对象 @EventListener事件监听方法适配为ApplicationListener
org.springframework.context.annotation. internalPersistenceAnnotationProcessor PersistenceAnnotationBeanPostProcessor对象 满足一定条件的情况下,处理JPA注解
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
//实现了BeanDefinitionRegistryPostProcessor → BeanFactoryPostProcessor → BeanFactoryPostProcessor 
//可以看出控制的是BeanFactory的生命周期
}

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
//实现了InstantiationAwareBeanPostProcessorAdapter → SmartInstantiationAwareBeanPostProcessor 
//      → InstantiationAwareBeanPostProcessor → BeanPostProcessor 
//所以控制的是Bean的生命周期
    public AutowiredAnnotationBeanPostProcessor() {
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);
        try {
            this.autowiredAnnotationTypes.add(ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
            this.logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
        } catch (ClassNotFoundException var2) {
        }
    }
}

public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
    public CommonAnnotationBeanPostProcessor() {
        this.setOrder(2147483644);
        //处理公共注解
        this.setInitAnnotationType(PostConstruct.class);
        this.setDestroyAnnotationType(PreDestroy.class);
        this.ignoreResourceType("javax.xml.ws.WebServiceContext");
    }
}

public class DefaultEventListenerFactory implements EventListenerFactory, Ordered {
    public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
        //传入Bean名称、class类型、方法、将其转化为一个适配器(Adapter),由适配器,将方法信息转化为一个ApplicationListener,原来是这么对Bean方法进行监听的
        return new ApplicationListenerMethodAdapter(beanName, type, method);
    }
}

//以下即为注解驱动下,内建依赖的Bean名称以及对应的Bean
public abstract class AnnotationConfigUtils {
    public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
    public static final String CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator";
    public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
    /** @deprecated */
    @Deprecated
    public static final String REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalRequiredAnnotationProcessor";
    public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalCommonAnnotationProcessor";
    public static final String PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalPersistenceAnnotationProcessor";
    private static final String PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME = "org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor";
    public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME = "org.springframework.context.event.internalEventListenerProcessor";
    public static final String EVENT_LISTENER_FACTORY_BEAN_NAME = "org.springframework.context.event.internalEventListenerFactory";
    private static final boolean jsr250Present;
    private static final boolean jpaPresent;
    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
        //-----------------------------
        //-------相当多的注册方法-------
        //-----------------------------
    }
}

以上仅为部分的内建对象,在Spring AOP 、Spring Boot中会有更多的内置对象,应该总结学习技巧,而不是背诵有哪些对象

Common Exception

依赖查找时,常见的一些异常

异常类型 触发条件 方法调用举例
NoSuchBeanDefinitionException 当查询的Bean在IoC容器中不存在时 BeanFactory#getBean
NoUniqueBeanDefinitionException 依赖查找时出现多个匹配Bean BeanFactory#getBean(Class)
BeanInstantiationException Bean所对应的类型不能被实例化、非具体类,(例如将接口或抽象类注册为Bean) BeanFactory#getBean
BeanCreationException Bean初始过程中出现异常幷抛出 @Postconstruct抛出异常
BeanDefinitionStoreException BeanDefinition配置元信息非法 XML资源无法访问到或无法打开,例如没有此XML或XML不可读

BeanException被设计为运行时异常,属于Spring设计上与JavaEE的区别点,因为Java抛出运行时异常,外层不需要强制进行try…catch


一点总结

一鼓作气、再而衰、三而竭,这篇文章写了两天,真的累了,写到后面实在是有心无力,并且因为长时间的坐着(上班 + 写文),早已坐得生疼、坐立不安,时间也已经到了2021年8月30日 23:56:06,写不动了,以后有精力了再来继续补充改文章


编写中未完待续…

文章作者: Administrator
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 AE86小行星
编程之路 Spring Java
喜欢就支持一下吧