【死磕Spring】| Spring IoC依赖查找:依赖注入还不够吗?依赖查找存在的价值几何?

Spring IoC依赖查找:依赖注入还不够吗?依赖查找存在的价值几何?

00、代码实现参考包的路径

1、DependencyLookUpDemo.java

2、User.java

3、SuperUser.java

4、context-dependency-lookup.xml

01、根据Bean名称进行查找

1.1、实时查找

  • 代码演示:

    • public static void main(String[] args) {
          //1.配置 xml 文件
          //2.启动 Spring 应用上下文
          BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml");
          lookUpInRealTime(beanFactory);
      }
      private static void lookUpInRealTime(BeanFactory beanFactory) {
          User user = (User) beanFactory.getBean("user");
          System.out.println("实时查找:"+user);
      }
      
  • 理论说明:其实就是简单的从IoC容器当中通过Bean名称获取对应的Bean

1.2、延迟查找

  • 代码演示:

    • public static void main(String[] args) {
          //1.配置 xml 文件
          //2.启动 Spring 应用上下文
          BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml");
          lookUpInLazy(beanFactory);
      }
      private static void lookUpInLazy(BeanFactory beanFactory){
          ObjectFactory<User> objectFactory = (ObjectFactory) beanFactory.getBean("objectFactory");
          User object = objectFactory.getObject();
          System.out.println("延迟查找:"+object);
      }
      
  • 理论说明:

    • 这里会出现一个我们之前没有看到的接口:ObjectFactory,它可以实现延迟查找的功能

    • 我们看下它的实现类:ObjectFactoryCreatingFactoryBean,它有一个属性:targetBeanName。我们在xml中配置这个Bean,并且将这个属性赋值,让它指定需要查找的对象。

    • <bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
          <property name="targetBeanName" value="user"/>
      </bean>
      
      
    • 所谓的延迟查找,我认为是,我们从IoC容器中可以直接拿到ObjectFactory这个Bean,如果不调用这个Bean的getObject方法的话,我们就不去IoC容器中查找User对象,当我们调用的时候,才会去IoC容器中去查

02、根据Bean类型进行查找

2.1、单个Bean对象

  • 代码演示:

    • public static void main(String[] args) {
          //1.配置 xml 文件
          //2.启动 Spring 应用上下文
          BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml");
          lookUpByType(beanFactory);
      }
      private static void lookUpByType(BeanFactory beanFactory){
          User bean = beanFactory.getBean(User.class);
          System.out.println("实时查找:"+bean);
      }
      
  • 理论说明:

    • 首先需要了解beanFactory#getBean(Class requiredType)这个方法是在spring 3.0之后开始支持的,因为spring 3.0才开始支持Java 5版本,Java 5版本开始全面支持泛型

    • 这段代码也挺简单的,就是通过 Bean的类型然后去IoC容器中去获取

    • 需要注意的是,如果容器中只有一个该类型的Bean的话,程序是正常的,一旦容器中有多个该Bean的类型的时候就会出现问题

      • Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.markus.spring.ioc.dependency.domain.User' available: expected single matching bean but found 2: user,super
        
      • 上面就是出现的异常,出现此异常不要担心,也非常好解决。我们打开xml文件,将你想要获取的Bean中配置上 primary=“true” 就可以了。也就是说,在IoC容器中,Bean的地位只有 “主要” 和 “其他”。最终在执行上段代码的时候,控制台就会打印出你配置primary的那个Bean对象。

2.2、集合Bean对象

  • 代码演示:

    • public static void main(String[] args) {
          //1.配置 xml 文件
          //2.启动 Spring 应用上下文
          BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml");
          lookUpCollectionByType(beanFactory);
      }
      private static void lookUpCollectionByType(BeanFactory beanFactory){
          if (beanFactory instanceof ListableBeanFactory){
              ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
              Map<String, User> beansOfType = listableBeanFactory.getBeansOfType(User.class);
              System.out.println("查找到的所有 User 集合对象:"+beansOfType);
          }
      }
      
  • 理论说明:

    • 这里又出现一个新的接口:ListableBeanFactory,本节只做简单演示,后续章节会对该接口做具体讲解,现在我们可以简单将它理解为:它里面有一个Map集合,这个Map集合存储着每一个类型对应的所有的实体Bean对象,例如:Map<String,User>
    • 剩下的就好理解了,通过判断该IoC容器的实例是否是ListableBeanFactory,如果是的话,说明该IoC容器中出现同一类型多个实例的情况。我们可以通过类型获取IoC容器中该类型对应的Map对象,然后打印出来

03、根据Java注解查找

  • 代码演示:

    • public static void main(String[] args) {
          //1.配置 xml 文件
          //2.启动 Spring 应用上下文
          BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-lookup.xml");
          lookUpByAnnotation(beanFactory);
      }
      private static void lookUpByAnnotation(BeanFactory beanFactory){
          if (beanFactory instanceof ListableBeanFactory){
              ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
              Map<String, Object> beansWithAnnotation = listableBeanFactory.getBeansWithAnnotation(Super.class);
              System.out.println(beansWithAnnotation);
          }
      }
      
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-huOSpdBg-1615988755471)(C:\Users\14222\AppData\Roaming\Typora\typora-user-images\image-20210312145254995.png)]

  • 理论解释:

    • 这里有个背景,看过我上面的参考路径你们就会知道,domain包下会有一个SuperUser的实体类,它打上了我们自定义的一个注解:Super,然后我们可以通过listableBeanFactory#getBeansWithAnnotation(Super.class)来获取打这个注解的实例Bean
    • 结果就如上图控制台中打印的一样,获取到SuperUser实例对象。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值