SpringIoc依赖查找-5

news2025/8/13 8:15:31

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

  • 单一类型依赖查找

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

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vrzgmly7-1669257924074)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112306129.png)]

    • JavaBeans - java.beans.beancontext.BeanContext

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1ER47wg-1669257924076)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112822387.png)]

  • 集合类型依赖查找

    • java.beans.beancontext.BeanContext

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DOUakDJL-1669257924076)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112827221.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BbGHg86B-1669257924076)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112849605.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XlcSZ6MM-1669257924077)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122112904560.png)]

      集合查找方法

  • 层次性依赖查找

    • java.beans.beancontext.BeanContext

      这里要集合 Java Beans Api

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CP5sDgqD-1669257924077)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122113537918.png)]

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vc6gDUz5-1669257924077)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221122113631987.png)]

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…)

          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlGW4QZa-1669257924078)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123110444600.png)]

          返回一个实例, 这个实例可能是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();
            }
        
            @Bean
            public String helloWord() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"
                return "hello word";
            }
        
        
            private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
                // 通常来说String类型的Bean Spring 上下文是不会定义的, 因此这个时候可以用 注意:只能查唯一Bean多个Bean会报错NoUniqueBeanDefinitionException
                ObjectProvider<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的初始化

            [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nCOG5tTX-1669257924078)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123133546661.png)]

        • 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 <- ConfigurableListableBeanFactory
                  ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
                  System.out.println("当前 BeanFactory 的 Parent BeanFactory : " + beanFactory.getParentBeanFactory());
          
                  ConfigurableListableBeanFactory parentBeanFactory = createParentBeanFactory();
          
                  // 2. 设置 Parent BeanFactory
                  beanFactory.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;
              }
          
          }
          
          
          // 运行结果
          当前 BeanFactoryParent BeanFactory : null
          当前 BeanFactoryParent 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

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

            [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uhtppiEk-1669257924079)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123151054825.png)]

      • 根据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 reference
                  beanProvider.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
              @Primary
              public String helloWord() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"
                  return "hello word";
              }
          
              @Bean
              public String message() { // @Bean没有value的时候 方法名称就是 Bean 名称 == "helloWord"
                  return "message";
              }
          
              private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
                  // 通常来说String类型的Bean Spring 上下文是不会定义的, 因此这个时候可以用 注意:只能查唯一Bean多个Bean会报错NoUniqueBeanDefinitionException
                  ObjectProvider<String> beanProvider = applicationContext.getBeanProvider(String.class);
                  System.out.println(beanProvider.getObject());
              }
          
          
          }
          
          
          // 运行结果
          hello word
          当前 User 对象 : User{id=1, name='xiaoge'}
          hello word
          message
          

6. 安全依赖查找

  • 依赖查找安全性对比

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qU0KbAWg-1669257924079)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123154119989.png)]

    注意:层次性依赖查找的安全性取决于其扩展的单一或集合类型的 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 ObjectFactory
            ObjectFactory<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' available
    	at 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' available
    	at 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 内建可查找的依赖

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9kofvJzg-1669257924080)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123164247234.png)]

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

    C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123164332343.png

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiJRKs5K-1669257924081)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123164505327.png)]

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jktjKKOn-1669257924081)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123170438893.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PidXZteP-1669257924082)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123170557025.png)]

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

  • BeansException子类型

    C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221123170857785.png

  • 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();
        }
    
        @Bean
        public String bean1() {
            return "bean1";
        }
    
        @Bean
        public String bean2() {
            return "bean2";
        }
    }
    
    
    // 运行结果
    Spring 应用上下文存在2java.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);
            // 注册Bean
            applicationContext.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 interface
    	at 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 interface
    	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:70)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1312)
    	... 11 more
    
    Process 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);
            // 注册Bean
            applicationContext.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...");
            }
    
            @Override
            public 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 more
    
    Process finished with exit code 1
    
    

9. 面试题精选

  • ObjectFactory 与BeanFactory 的区别?

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

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

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

    根据名称查找

    C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124100431367.png

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8nJA3QGQ-1669257924083)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124100527299.png)]

    C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124100618961.png

    根据类型查找

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-89L10AE8-1669257924084)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124102640878.png)]

    C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124102627020.png

    C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124102750503.png

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-713k2XRX-1669257924085)(C:\Users\13301\AppData\Roaming\Typora\typora-user-images\image-20221124102926690.png)]

    最终还是用了BeanFactory

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/33312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于android的移动学习平台(前端APP+后端Java和MySQL)

一、需求规格说明书 1&#xff0e;概述 1.1项目目的与目标, &#xff08;1&#xff09; 项目目的&#xff1a;设计并实现网络化的在线学习系统&#xff0c;对校内课程教学进行辅助&#xff0c;为学生和教师提供一个良好的互动平台&#xff0c;方便学生课后获取学习资源和进行交…

阿里云负载均衡SLB,HTTPS动态网站部署负载均衡,实现高并发流量分发

第一步购买服务器&#xff0c;测的话一般就用按量付费几毛钱一小时 我是用了三台&#xff0c;一台是常用的服务器&#xff0c;两台临时服务器进行部署项目 2&#xff1a;服务器购买完之后&#xff0c;开始安装项目运行环境&#xff0c;我是宝塔一键按键的&#xff0c;PHP7.1。…

新知实验室-基于腾讯云音视频TRTC的微信小程序实践

前言 腾讯会议是我们常用的一款线上会议软体&#xff0c;如果想要使用&#xff0c;我们需要下载软体使用&#xff0c;相比之下&#xff0c;基于腾讯云音视频的TRTC提供了一个很好的解决方案&#xff0c;我们通过接入到小程序中来实现快捷的开始会议&#xff0c;加入会议。 TR…

[Power Query] 删除错误/空值

数据导入后&#xff0c;有可能出现错误(Error)或者空值(null) &#xff0c;我们需要对此进行删除。为此&#xff0c;本文通过讲解Power Query中的删除错误/空值操作&#xff0c;帮助大家的同时也便于日后自身的复盘学习 数据源 将数据源导入到Power BI Desktop&#xff0c;单击…

VSCode中Prettier插件依赖安装及冲突解决

文章目录一、Prettier插件安装1.1 安装Prettier插件1.2 添加Prettier配置文件1.3 配置格式化工具1.4 配置自动格式化1.5 与ESLint冲突解决二、Prettier依赖安装2.1 安装依赖2.2 配置2.3 配置指令2.4 其他配置和冲突解决一、Prettier插件安装 1.1 安装Prettier插件 通过VSCode…

[附源码]计算机毕业设计JAVA流浪动物救助系统

[附源码]计算机毕业设计JAVA流浪动物救助系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybati…

【算法基础】(一)基础算法 --- 快速排序

✨个人主页&#xff1a;bit me ✨当前专栏&#xff1a;算法基础 &#x1f525;专栏简介&#xff1a;该专栏主要更新一些基础算法题&#xff0c;有参加蓝桥杯等算法题竞赛或者正在刷题的铁汁们可以关注一下&#xff0c;互相监督打卡学习 &#x1f339; &#x1f339; &#x1f3…

游戏品类加速回暖,文娱内容持续火热——2022年IAA行业品类发展洞察系列报告·第三期

易观分析&#xff1a;易观分析联合穿山甲与巨量算数共同构建IAA发展指数&#xff0c;通过行业规模、内容热度、商业变现的多维数据指标反映行业细分品类的发展情况&#xff0c;对领域季度运行情况、热门品类进行分析解读&#xff0c;助力开发者深入洞察领域特性和发展趋势&…

【American English】美语的连读规则

文章目录连读规则1. 辅音 元音2. 辅音 辅音情形1: 相同或相近的辅音相遇情形2: 辅音 h情形3: 爆破音 [l] / [m] / [n]情形4: 爆破音 [f] / [v]情形5: 爆破音 [tf]/[]3. 元音 元音情形1: 嘴唇变平时增加 [y] 音情形2: 嘴唇变圆时增加 [w] 音4. 特殊辅音 yRef连读规则 英…

open-set recognition(OSR)开集识别

开集识别 闭集识别 ​ 训练集中的类别和测试集中的类别是一致的&#xff0c;最常见的就是使用公开数据集进行训练&#xff0c;所有数据集中的图像的类别都是已知的&#xff0c;没有未知种类的图像。传统的机器学习的算法在这些任务上已经取得了比较好的效果。 &#xff08;训…

简述供应商管理SRM系统

简道云SRM管理系统供应商关系管理(SRM系统)&#xff0c;是企业可以用来对供应商的优势和能力进行系统的、全行业范围的评估&#xff0c;涉及企业整体的商业战略&#xff0c;供应商寻源、采购审批、比价、招投标管理、订单执行、库存可视化管理、财务支付审批对账、供应商绩效评…

java--并发

并发1.java的线程状态&#xff08;1&#xff09;sleep wait的区别和联系2.线程池的核心参数3.lock 和 synchronized4.volatile能否保证线程安全5.java中的悲观锁和乐观锁6.Hashtable和ConcurrentHashMap7.对ThreadLocal1.java的线程状态 new 新建&#xff1a;普通的类&#xf…

流媒体技术基础-流媒体服务与框架

一、开源流媒体服务器 38款 流媒体服务器开源软件 主流的开源流媒体服务器及框架如下&#xff1a; 1.Live555 [RTSP拉流] 一个为流媒体提供解决方案的跨平台的C开源项目&#xff0c;它实现了对标准流媒体传输协议如 RTP/RTCP、RTSP、SIP等的支持。 实现了对多种音视频编码格…

【毕业设计】机器学习的溢油特征提取与识别

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着准备考研,考公,考教资或者实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过…

城市内涝地埋式积水监测系统解决方案

一、方案背景 近 20 年来&#xff0c;我国城市化进程加快&#xff0c;城市地区由于人口密集&#xff0c;物资财产密度不断加大等特点&#xff0c;高强度暴雨积水形成的洪涝灾害对城市化地区产生的威肋和带来的狠失愈来愈大。由于城市的不断扩建&#xff0c;使工业区、商业区和居…

dos2unix和unix2dos

一 单次转换 用于转换Windows和UNIX的换行符&#xff0c;通常在windows系统中开发的源码文件&#xff0c;换行符是\r\n,二linux中的文件的换行符是\n。如果不转行可能会出错。在windows记事本写一个hello world源码. #include <stdio.h>int main(void) {printf("h…

Jmeter快速入门

Jmeter依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了JDK&#xff0c;并且配置了环境变量。 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具&#xff0c;用于对软件做压力测试。 JMeter 最初被设计用于 Web 应用测试&#xff0c;但后来扩展到了其他测试…

【Python百日进阶-WEB开发-冲進Flask】Day182 - Flask蓝图与模板继承

文章目录一、day02项目环境和结构搭建1.1 项目根目录创建apps包1.2 项目模板目录templates创建user子目录二、后端知识要点2.1 蓝图Blueprint基础知识2.1.1 为什么需要蓝图2.1.2 什么是蓝图2.1.3 蓝图的属性2.1.4 蓝图使用的步骤2.1.4.1 创建一个蓝图的包,例如user,并在view.py…

蓝牙耳机什么牌子音质最好?音质超好的蓝牙耳机推荐

蓝牙耳机在便捷性上&#xff0c;没有线材的蓝牙耳机&#xff0c;日常通勤、运动、平时走路佩戴&#xff0c;那种因为无线而带来的无缠绕感觉都是有线耳机无法媲美的&#xff0c;但是音质很多人都会觉得有线的好&#xff0c;由于近几年耳机市场的不断进步&#xff0c;很多蓝牙耳…

《痞子衡嵌入式半月刊》 第 67 期

痞子衡嵌入式半月刊&#xff1a; 第 67 期 这里分享嵌入式领域有用有趣的项目/工具以及一些热点新闻&#xff0c;农历年分二十四节气&#xff0c;希望在每个交节之日准时发布一期。 本期刊是开源项目(GitHub: JayHeng/pzh-mcu-bi-weekly)&#xff0c;欢迎提交 issue&#xff0c…