1. 依赖查找的今世前生: Spring IoC容器从Java标准中学到了什么?

  • 单一类型依赖查找

    • JNDI - javax.naming.Context#lookup(javax.naming.Name)

    • JavaBeans - java.beans.beancontext.BeanContext

  • 集合类型依赖查找

    • java.beans.beancontext.BeanContext

      集合查找方法

  • 层次性依赖查找

    • java.beans.beancontext.BeanContext

      这里要集合 Java Beans Api

2. 单一类型依赖查找: 如何查找已知名称或类型的Bean对象?

  • 单一类型依赖查找接口- BeanFactory

    • 根据Bean名称查找

      • getBean(String)

      • Spring 2.5覆盖默认参数:getBean(String,Object…)

    • 根据 Bean类型查找

      • Bean实时查找

        • Spring 3.0 getBean(Class)

        • Spring 4.1覆盖默认参数:getBean(Class,Object…)

          返回一个实例, 这个实例可能是shared(单例)可能是independent(原生), 这里就会告诉你一个不好的特点, 如果是shared的话, 当你的整个一个BeanFactory实例里面, 这个容器里面包含了同样一个实例, 那么之后你每次调用一次就会覆盖它的方法, 这个方式实际上有点不可取的, 那么因此建议采用 BeanFactory 的方式只好是只读方法, 要不你就完全的覆盖相关定义, 比如说你吧以前的BeanDefinition把它进行删除, 后面做一个Override做一个覆盖

    • Spring 5.1 Bean延迟查找

      • pom.xml

        <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.2.RELEASE</version></dependency>
        
      • getBeanProvider(Class)

        package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.factory.ObjectProvider;
        import org.springframework.context.annotation.AnnotationConfigApplicationContext;
        import org.springframework.context.annotation.Bean;/*** * 通过{@link ObjectProvider} 进行依赖查找* * @PACKAGE_NAME: org.xiaoge.thinking.in.spring.dependency.lookup* @Classname ObjectProviderDemo* @Date 2022/11/23 11:23* @Author zhangxiao* @Description TODO*/
        public class ObjectProviderDemo {  // @Configuration 是非必须注解public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 将当前类 ObjectProviderDemo 作为配置类 (Configuration class)applicationContext.register(ObjectProviderDemo.class);// 启动应用上下文applicationContext.refresh();// 依赖查找集合对象lookupByObjectProvider(applicationContext);// 关闭应用上下文applicationContext.close();}@Beanpublic String helloWord() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"return "hello word";}private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {// 通常来说String类型的Bean Spring 上下文是不会定义的, 因此这个时候可以用 注意:只能查唯一Bean多个Bean会报错NoUniqueBeanDefinitionExceptionObjectProvider<String> beanProvider = applicationContext.getBeanProvider(String.class);System.out.println(beanProvider.getObject());}}// 运行结果
        hello word
        
      • getBeanProvider(ResolvableType)

        后面写

    • 根据Bean名称+类型查找: getBean(String,Class)

    • 建议: 不要用覆盖默认参数的形式去查找

3. 集合类型依赖查找: 如何查找已知类型多个Bean集合?

  • 集合类型依赖查找接口- ListableBeanFactory

    • 根据Bean类型查找

      • 获取同类型Bean名称列表

        • getBeanNamesForType(Class)

          • 注意: 这个方法比较BeanDefinition里面的getBeanClassName和FactoryBean里面的getObjectType类型的匹配情况, 所以这个时候还没有涉及到Bean的初始化

        • Spring 4.2 getBeanNamesForType(ResolvableType)

      • 获取同类型Bean 实例列表

        • getBeansOfType(Class)以及重载方法

          • 注意: 它会涉及到Bean的初始化, 这个方法可能 会提前把一些你的类进行初始化, 初始化之后会导致一些Bean初始化并不完全, 这个时候会导致一些位置的错误, 所以在判断的时候首先去通过名称去判断, 然后再去通过类型判断, 这样的话比较好一点
    • 通过注解类型查找

      • Spring 3.0获取标注类型Bean名称列表

        • getBeanNamesForAnnotation(Class<? extends Annotation>)
      • Spring 3.0获取标注类型Bean 实例列表
        • getBeansWithAnnotation(Class<? extends Annotation>)
      • Spring 3.0 获取指定名称+标注类型Bean实例
        • findAnnotationOnBean(String,Class<? extends Annotation>)

4. 层次性依赖查找: 依赖查找也有双亲委派?

  • 层次性依赖查找接口– HierarchicalBeanFactory

    • 双亲BeanFactory: getParentBeanFactory()

    • 层次性查找

      • 根据 Bean名称查找

        • 基于containsLocalBean方法实现

          package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.factory.BeanFactory;
          import org.springframework.beans.factory.HierarchicalBeanFactory;
          import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
          import org.springframework.beans.factory.support.DefaultListableBeanFactory;
          import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
          import org.springframework.context.annotation.AnnotationConfigApplicationContext;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;/**** 层次性 依赖查找 示例** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.dependency.lookup* @Classname HierarchicalDependencyLookupDemo* @Date 2022/11/23 13:52* @Author zhangxiao* @Description TODO*/
          public class HierarchicalDependencyLookupDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 讲当前类 HierarchicalDependencyLookupDemo 作为配置类 (Configuration Class)applicationContext.register(HierarchicalDependencyLookupDemo.class);// 1. 获取HierarchicalBeanFactory <- ConfigurableBeanFactory <- ConfigurableListableBeanFactoryConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();System.out.println("当前 BeanFactory 的 Parent BeanFactory : " + beanFactory.getParentBeanFactory());ConfigurableListableBeanFactory parentBeanFactory = createParentBeanFactory();// 2. 设置 Parent BeanFactorybeanFactory.setParentBeanFactory(parentBeanFactory);System.out.println("当前 BeanFactory 的 Parent BeanFactory : " + beanFactory.getParentBeanFactory());// 启动应用上下文applicationContext.refresh();// 当前 Bean 是否在当前容器中displayContainsLocalBean(beanFactory, "user");displayContainsLocalBean(parentBeanFactory, "user");// 当前 Bean 是否在容器中 实现双亲委派displayContainsBean(beanFactory, "user");displayContainsBean(parentBeanFactory, "user");// 关闭应用上下文applicationContext.close();}/*** 查询 Bean 是否 在容器中 实现双亲委派* @param beanFactory* @param beanName*/private static void displayContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {System.out.printf("当前 BeanFactory[%s] 是否包含 Bean[name : %s] : %s\n", beanFactory, beanName, containsBean(beanFactory, beanName));}/*** 递归实现, 查找 Bean 这是 BeanFactoryUtils 没有实现的* @param beanFactory* @param beanName* @return*/private static Boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {if (beanFactory.containsLocalBean(beanName)) {return true;}// 获取父容器BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();// 判断了类型也判断了它是否为空if (parentBeanFactory instanceof HierarchicalBeanFactory) {// 转换类型HierarchicalBeanFactory parentHierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parentBeanFactory);if (parentHierarchicalBeanFactory.containsLocalBean(beanName)) {return true;}containsBean(parentHierarchicalBeanFactory, beanName);}return false;}/*** 当前 bean 是否在 当前备本地(它自己的容器)容器中* @param beanFactory* @param beanName*/private static void displayContainsLocalBean(HierarchicalBeanFactory beanFactory, String beanName) {System.out.printf("当前 BeanFactory[%s] 是否包含 Local Bean[name : %s] : %s\n", beanFactory, beanName, beanFactory.containsLocalBean(beanName));}/**** @return*/private static ConfigurableListableBeanFactory createParentBeanFactory() {// 创建BeanFactory容器DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);// XML 配置文件 ClassPath 路径String location = "classpath:META-INF/dependency-lookup-context.xml";// 加载配置reader.loadBeanDefinitions(location);return beanFactory;}}// 运行结果
          当前 BeanFactory 的 Parent BeanFactory : null
          当前 BeanFactory 的 Parent BeanFactory : org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b: defining beans [user,objectFactory,superUser]; root of factory hierarchy
          当前 BeanFactory[org.springframework.beans.factory.support.DefaultListableBeanFactory@1e397ed7: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,hierarchicalDependencyLookupDemo]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b] 是否包含 Local Bean[name : user] : false
          当前 BeanFactory[org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b: defining beans [user,objectFactory,superUser]; root of factory hierarchy] 是否包含 Local Bean[name : user] : true
          当前 BeanFactory[org.springframework.beans.factory.support.DefaultListableBeanFactory@1e397ed7: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,hierarchicalDependencyLookupDemo]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b] 是否包含 Bean[name : user] : true
          当前 BeanFactory[org.springframework.beans.factory.support.DefaultListableBeanFactory@3c09711b: defining beans [user,objectFactory,superUser]; root of factory hierarchy] 是否包含 Bean[name : user] : true
      • 根据 Bean类型查找实例列表

        • 单一类型: BeanFactoryUtils#beanOfType

        • 集合类型:BeanFactoryUtils#beansOfTypeIncludingAncestors

          • 注意: 改方法实现了双亲委派的原则

      • 根据Java 注解查找名称列表

        • BeanFactoryUtils#beanNamesForTypeIncludingAncestors

5. 延迟依赖查找: 非延迟初始化Bean也能实现延迟查找?

  • Bean延迟依赖查找接口

    • org. springframework. beans.factory.ObjectFactory

    • org. springframework. beans.factory.ObjectProvider

      • Spring 5 对Java 8 特性扩展

        • 函数式接口

          • getIfAvailable (Supplier)
          • ifAvailable (Consumer)
        • Stream扩展- stream ()

          package org.xiaoge.thinking.in.spring.dependency.lookup;import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
          import org.springframework.beans.factory.ObjectProvider;
          import org.springframework.context.annotation.AnnotationConfigApplicationContext;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Primary;
          import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/**** 通过{@link ObjectProvider} 进行依赖查找** @PACKAGE_NAME: org.xiaoge.thinking.in.spring.dependency.lookup* @Classname ObjectProviderDemo* @Date 2022/11/23 11:23* @Author zhangxiao* @Description TODO*/
          public class ObjectProviderDemo {  // @Configuration 是非必须注解public static void main(String[] args) {// 创建 ApplicationContext 容器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> beanProvider = applicationContext.getBeanProvider(String.class);
          //        Iterable<String> stringIterable = beanProvider;
          //        for (String s : stringIterable) {//            System.out.println(s);
          //        }// Stream -> Method referencebeanProvider.stream().forEach(System.out::println);}/*** 这是个兜底方案, 当没有User Bean 不在容器中时  使用 自己的* @param applicationContext*/private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {ObjectProvider<User> beanProvider = applicationContext.getBeanProvider(User.class);User user = beanProvider.getIfAvailable(User::createUser);System.out.println("当前 User 对象 : " + user);}@Bean@Primarypublic String helloWord() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"return "hello word";}@Beanpublic String message() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"return "message";}private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {// 通常来说String类型的Bean Spring 上下文是不会定义的, 因此这个时候可以用 注意:只能查唯一Bean多个Bean会报错NoUniqueBeanDefinitionExceptionObjectProvider<String> beanProvider = applicationContext.getBeanProvider(String.class);System.out.println(beanProvider.getObject());}}// 运行结果
          hello word
          当前 User 对象 : User{id=1, name='xiaoge'}
          hello word
          message
          

6. 安全依赖查找

  • 依赖查找安全性对比

    注意:层次性依赖查找的安全性取决于其扩展的单一或集合类型的 BeanFactory 接口

    package org.xiaoge.thinking.in.spring.dependency.lookup;import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.ListableBeanFactory;
    import org.springframework.beans.factory.ObjectFactory;
    import org.springframework.beans.factory.ObjectProvider;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.xiaoge.thinking.in.spring.ioc.overview.domain.User;/*** 类型安全 依赖查找 示例** @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a>* @since*/
    public class TypeSafetyDependencyLookupDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 将当前类 TypeSafetyDependencyLookupDemo 作为配置类 (Configuration class)applicationContext.register(TypeSafetyDependencyLookupDemo.class);// 启动应用上下文applicationContext.refresh();// 演示 BeanFactory#getBean 方法的安全性displayBeanFactoryGetBean(applicationContext);// 演示 ObjectFactory#getObject 方法的安全性displayObjectFactoryGetObject(applicationContext);// 演示 ObjectProvider#ifAvailable 方法的安全性displayObjectProviderIfAvailable(applicationContext) ;// 演示 ListableBeanFactory#getBeansOfType 方法的安全性displayListableBeanFactoryGetBeansOfType(applicationContext);// 演示 ObjectProvider Stream 操作的安全性displayObjectProviderStreamOps(applicationContext);// 关闭应用上下文applicationContext.close();}/*** ObjectProvider* @param applicationContext*/private static void displayObjectProviderStreamOps(AnnotationConfigApplicationContext applicationContext) {ObjectProvider<User> objectProvider = applicationContext.getBeanProvider(User.class);printBeansException("displayObjectProviderStreamOps", () -> objectProvider.forEach(System.out::println));}/*** ListableBeanFactory#getBeansOfType 是否安全* @param beanFactory*/private static void displayListableBeanFactoryGetBeansOfType(ListableBeanFactory beanFactory) {printBeansException("displayListableBeanFactoryGetBeansOfType", () -> beanFactory.getBeansOfType(User.class));}/*** ObjectProvider#getIfAvailable 是否安全* @param applicationContext*/private static void displayObjectProviderIfAvailable(AnnotationConfigApplicationContext applicationContext) {ObjectProvider<User> objectProvider = applicationContext.getBeanProvider(User.class);printBeansException("displayObjectProviderIfAvailable", () -> objectProvider.getIfAvailable());}/*** ObjectFactory#getObject 是否安全* @param applicationContext*/private static void displayObjectFactoryGetObject(AnnotationConfigApplicationContext applicationContext) {// ObjectProvider is ObjectFactoryObjectFactory<User> objectFactory = applicationContext.getBeanProvider(User.class);printBeansException("displayObjectFactoryGetObject", () -> objectFactory.getObject());}/*** BeanFactory#getBean 是否安全* @param applicationContext*/private static void displayBeanFactoryGetBean(AnnotationConfigApplicationContext applicationContext) {printBeansException("displayBeanFactoryGetBean", () -> applicationContext.getBean(User.class));}/*** 打印异常信息* @param source* @param runnable*/private static void printBeansException(String source, Runnable runnable) {System.err.println("===========================================");System.err.println("Source from : " + source);try {runnable.run();} catch (BeansException e) {e.printStackTrace();}}}// 运行结果
    ===========================================
    Source from : displayBeanFactoryGetBean
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.xiaoge.thinking.in.spring.ioc.overview.domain.User' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1126)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.lambda$displayBeanFactoryGetBean$4(TypeSafetyDependencyLookupDemo.java:90)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.printBeansException(TypeSafetyDependencyLookupDemo.java:103)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.displayBeanFactoryGetBean(TypeSafetyDependencyLookupDemo.java:90)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.main(TypeSafetyDependencyLookupDemo.java:30)
    ===========================================
    Source from : displayObjectFactoryGetObject
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.xiaoge.thinking.in.spring.ioc.overview.domain.User' availableat org.springframework.beans.factory.support.DefaultListableBeanFactory$1.getObject(DefaultListableBeanFactory.java:370)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.lambda$displayObjectFactoryGetObject$3(TypeSafetyDependencyLookupDemo.java:82)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.printBeansException(TypeSafetyDependencyLookupDemo.java:103)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.displayObjectFactoryGetObject(TypeSafetyDependencyLookupDemo.java:82)at org.xiaoge.thinking.in.spring.dependency.lookup.TypeSafetyDependencyLookupDemo.main(TypeSafetyDependencyLookupDemo.java:33)
    ===========================================
    Source from : displayObjectProviderIfAvailable
    ===========================================
    Source from : displayListableBeanFactoryGetBeansOfType
    ===========================================
    Source from : displayObjectProviderStreamOps
    

    由此可见建议使用ObjectProvider来进行依赖查找

7. 内建可查找的依赖: 那些Spring IoC容器内建依赖可供查找?

  • AbstractApplicationContext 内建可查找的依赖

  • 注解驱动Spring 应用上下文内建可查找的依赖(部分)

    其实也非常好记, 只需要关注AnnotationConfigUtils就知道了

8. 依赖查找中的经典异常: Bean找不到?Bean不唯一的?Bean创建失败?

  • BeansException子类型

  • NoSuchBeanDefinitionException不做演示, 上面案例有

  • NoUniqueBeanDefinitionException

    package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;/*** {@link NoUniqueBeanDefinitionException} 示例代码** @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a>* @since*/
    public class NoUniqueBeanDefinitionExceptionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 将当前类 NoUniqueBeanDefinitionExceptionDemo 作为配置类 (Configuration class)applicationContext.register(NoUniqueBeanDefinitionExceptionDemo.class);// 启动应用上下文applicationContext.refresh();// 由于 Spring 上下文存在两个String类型的 Bean, 通过单一类型查找会报错try {applicationContext.getBean(String.class);} catch (NoUniqueBeanDefinitionException e) {System.err.printf("Spring 应用上下文存在%d个 %s 类型的Bean, 具体原因: %s",e.getNumberOfBeansFound(),String.class.getName(),e.getMessage());}// 关闭应用上下文applicationContext.close();}@Beanpublic String bean1() {return "bean1";}@Beanpublic String bean2() {return "bean2";}
    }// 运行结果
    Spring 应用上下文存在2个 java.lang.String 类型的Bean, 具体原因: No qualifying bean of type 'java.lang.String' available: expected single matching bean but found 2: bean1,bean2
  • BeanInstantiationException

    package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.BeanInstantiationException;
    import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** {@link BeanInstantiationException} 示例** @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a>* @since*/
    public class BeanInstantiationExceptionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 BeanDefinition Bean Class 是一个 CharSequence 接口BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(CharSequence.class);// 注册BeanapplicationContext.registerBeanDefinition("errorBean", beanDefinitionBuilder.getBeanDefinition());// 启动应用上下文applicationContext.refresh();// 关闭应用上下文applicationContext.close();}}// 运行结果
    十一月 23, 2022 5:56:42 下午 org.springframework.context.support.AbstractApplicationContext refresh
    警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.lang.CharSequence]: Specified class is an interface
    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.lang.CharSequence]: Specified class is an interfaceat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1320)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1214)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)at org.xiaoge.thinking.in.spring.dependency.lookup.BeanInstantiationExceptionDemo.main(BeanInstantiationExceptionDemo.java:28)
    Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.lang.CharSequence]: Specified class is an interfaceat org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:70)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1312)... 11 moreProcess finished with exit code 1
  • BeanCreationException

    package org.xiaoge.thinking.in.spring.dependency.lookup;import org.springframework.beans.factory.BeanCreationException;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;import javax.annotation.PostConstruct;/*** {@link BeanCreationException} 示例** @author <a href="mailto:1330137071@qq.com">Zhang Xiao</a>* @since*/
    public class BeanCreationExceptionDemo {public static void main(String[] args) {// 创建 ApplicationContext 容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 注册 BeanDefinition Bean Class 是一个 POJO 普通类,不过初始化方法回调时抛出异常BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(POJO.class);// 注册BeanapplicationContext.registerBeanDefinition("errorBean", beanDefinitionBuilder.getBeanDefinition());// 启动应用上下文applicationContext.refresh();// 关闭应用上下文applicationContext.close();}static class POJO implements InitializingBean {@PostConstruct // CommonAnnotationBeanPostProcessor 实现的这个注解, 顺序很重要, 因为PostConstruct注解装饰的方法会先执行public void init() throws Exception {throw new Exception("init() : For purposes...");}@Overridepublic void afterPropertiesSet() throws Exception {throw new Exception("afterPropertiesSet() : For purposes...");}}}// 运行结果
    十一月 23, 2022 5:57:12 下午 org.springframework.context.support.AbstractApplicationContext refresh
    警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean': Invocation of init method failed; nested exception is java.lang.Exception: init() : For purposes...
    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorBean': Invocation of init method failed; nested exception is java.lang.Exception: init() : For purposes...at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)at org.xiaoge.thinking.in.spring.dependency.lookup.BeanCreationExceptionDemo.main(BeanCreationExceptionDemo.java:28)
    Caused by: java.lang.Exception: init() : For purposes...at org.xiaoge.thinking.in.spring.dependency.lookup.BeanCreationExceptionDemo$POJO.init(BeanCreationExceptionDemo.java:38)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)... 12 moreProcess finished with exit code 1

9. 面试题精选

  • ObjectFactory 与BeanFactory 的区别?

    答: 0bjectFactory 与 BeanFactory 均提供依赖查找的能力。

    不过 ObjectFactory 仅关注一个 或一种类型的 Bean 依赖查找, 并且自身不具备依赖查找的能力,能力则由 BeanFactory 输出。

    BeanFactory则提供了单一类型、集合类型以及层次性等多种依赖查找方式。

    根据名称查找

    根据类型查找

    最终还是用了BeanFactory

    可以通过改文章, 可以看出它是怎么通过ObjectFactoryCreatingFactoryBean创建ObjectFactory的

  • BeanFactory. getBean操作是否线程安全?

    答: BeanFactory. getBean方法的执行是线程安全的,操作过程中会增加互斥锁。

SpringIoc依赖查找-5相关推荐

  1. 通过ObjectProvider进行依赖查找

    public class ObjectProviderDemo { // @Configuration 是非必须注解public static void main(String[] args) {// ...

  2. 参数依赖查找(ADL,Argument-dependent lookup)

    参数依赖查找(Argument-dependent lookup),又称 ADL 或 Koenig 查找,是一组于函数调用表达式查找非限定函数名的规则,包含对重载运算符的隐式函数调用.在通常非限定名称 ...

  3. Spring依赖查找中的常见异常

    文章目录 BeansException的子接口 NoSuchBeanDefinitionException不存在要查找的Bean NoUniqueBeanDefinitionException 容器中 ...

  4. Spring安全依赖查找

    依赖查找安全性对比 依赖查找类型 代表实现 是否安全 单一类型 BeanFactory#getBean 否 ObjectFactory#getObject 否 ObjectProvider#getIf ...

  5. Spring 延迟依赖查找Bean

    Bean 延迟依赖查找接口 // 一个对象工厂 public interface ObjectFactory<T> {// 返回一个对象T getObject() throws Beans ...

  6. Spring 层次性依赖查找Bean

    层次性依赖查找接口 - HierarchicalBeanFactory 双亲 BeanFactory:getParentBeanFactory() 层次性查找 根据 Bean 名称查找 基于 cont ...

  7. Spring集合类型依赖查找

    集合类型依赖查找接口 - ListableBeanFactory 根据 Bean 类型查找 获取同类型 Bean 名称列表 getBeanNamesForType(Class) getBeanName ...

  8. Spring单一类型依赖查找Bean

    单一类型依赖查找接口 - BeanFactory BeanFacotry是spring中比较原始的Factory,BeanFactory是个Factory,也就是IOC容器或对象工厂 根据Bean名称 ...

  9. Java J2EE中的依赖查找

    个人看法:设计依赖查找的设计模式,是为了解耦. 单一类型依赖查找 JNDI javax.naming.Context#lookup JavaBeans java.beans.beancontext.B ...

最新文章

  1. Django Web开发学习笔记(4)
  2. 三维渲染引擎设计与实践(四)
  3. 7.Redis常用命令:ZSet
  4. 美团Android DEX自动拆包及动态加载简介
  5. .net ajax 怎么写,.NET学习篇--Ajax中Url的写法
  6. Price determination entry point - how is 4.85 calculated
  7. springboot2.x 从零到一(1、快速创建服务)
  8. [转]很经典的http协议详解
  9. 3月22 关于CSS
  10. 日历表(点击每一日获得当日日期)
  11. php多层if函数,if函数嵌套计算公式用法
  12. python根据汉字获得拼音,python获取一组汉字拼音首字母的方法 -电脑资料
  13. 刷手机二维码轻松登机(仅限移动用户)
  14. python 爬虫论_python爬虫——论抓包的正确姿势和学好Javascript的重要性(1)
  15. 启动虚拟机,电脑蓝屏强制自动重启问题解决
  16. 记录一次redis莫名其妙丢失token的解决方案
  17. ADN: Artifact Disentanglement Network for Unsupervised Metal Artifact Reduction
  18. 几款常用LED显示屏驱动芯片介绍及选择VK1624
  19. java如果判断文件夹或文件不存在就创建文件夹或文件
  20. 摄影镜头调制传输函数MTF解读

热门文章

  1. linux 命令中 ! 加命令是啥意思
  2. 【快速幂】HRBUST 2263 萝莉控型提督
  3. delve应该安装到哪_使用 Delve 代替 Println 来调试 Go 程序 | Linux 中国
  4. Golang调试工具Delve使用简介
  5. Facebook官方商务插件全新上线,Ueeshop国内首家对接!
  6. 2019年出版新书目录_上海译文公布2019年“新书目录” 名家名译作品结集出版...
  7. SVG阴影、渐变,文字
  8. dump文件 修复iat_在OD中手工修复IAT重定向
  9. PE格式:导入表与IAT内存修正
  10. 使用cad转换器操作教程