深入理解Spring中的Lookup(方法注入)

 更新时间:2018年05月18日 10:26:18   作者:BeginnerH  
“Lookup方法”可以使Spring替换一个bean原有的,获取其它对象具体的方法,并自动返回在容器中的查找结果。下面这篇文章主要给大家介绍了关于Spring中Lookup(方法注入)的相关资料,需要的朋友可以参考下

前言

本文主要给大家介绍了关于Spring中Lookup(方法注入)的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍:

在使用Spring时,可能会遇到这种情况:一个单例的Bean依赖另一个非单例的Bean。如果简单的使用自动装配来注入依赖,就可能会出现一些问题,如下所示:

单例的Class A

@Component
public class ClassA {
 @Autowired
 private ClassB classB;

 public void printClass() {
  System.out.println("This is Class A: " + this);
  classB.printClass();
 }
}

非单例的Class B

@Component
@Scope(value = SCOPE_PROTOTYPE)
public class ClassB {
  public void printClass() {
    System.out.println("This is Class B: " + this);
  }
}

这里Class A采用了默认的单例scope,并依赖于Class B, 而Class B的scope是prototype,因此不是单例的,这时候跑个测试就看出这样写的问题:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {ClassA.class, ClassB.class})
public class MyTest {
  @Autowired
  private ClassA classA;

  @Test
  public void simpleTest() {
    for (int i = 0; i < 3; i++) {
      classA.printClass();
    }
  }
}

输出的结果是:

This is Class A: ClassA@282003e1
This is Class B: ClassB@7fad8c79
This is Class A: ClassA@282003e1
This is Class B: ClassB@7fad8c79
This is Class A: ClassA@282003e1
This is Class B: ClassB@7fad8c79

可以看到,两个类的Hash Code在三次输出中都是一样。Class A的值不变是可以理解的,因为它是单例的,但是Class B的scope是prototype却也保持Hash Code不变,似乎也成了单例?

产生这种的情况的原因是,Class A的scope是默认的singleton,因此Context只会创建Class A的bean一次,所以也就只有一次注入依赖的机会,容器也就无法每次给Class A提供一个新的Class B。

不那么好的解决方案

要解决上述问题,可以对Class A做一些修改,让它实现ApplicationContextAware。

@Component
public class ClassA implements ApplicationContextAware {
  private ApplicationContext applicationContext;

  public void printClass() {
    System.out.println("This is Class A: " + this);
    getClassB().printClass();
  }

  public ClassB getClassB() {
    return applicationContext.getBean(ClassB.class);
  }

  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }
}

这样就能够在每次需要到Class B的时候手动去Context里找到新的bean。再跑一次测试后得到了以下输出:

This is Class A: com.devhao.ClassA@4df828d7
This is Class B: com.devhao.ClassB@31206beb
This is Class A: com.devhao.ClassA@4df828d7
This is Class B: com.devhao.ClassB@3e77a1ed
This is Class A: com.devhao.ClassA@4df828d7
This is Class B: com.devhao.ClassB@3ffcd140

可以看到Class A的Hash Code在三次输出中保持不变,而Class B的却每次都不同,说明问题得到了解决,每次调用时用到的都是新的实例。

但是这样的写法就和Spring强耦合在一起了,Spring提供了另外一种方法来降低侵入性。

@Lookup

Spring提供了一个名为@Lookup的注解,这是一个作用在方法上的注解,被其标注的方法会被重写,然后根据其返回值的类型,容器调用BeanFactory的getBean()方法来返回一个bean。

@Component
public class ClassA {
  public void printClass() {
    System.out.println("This is Class A: " + this);
    getClassB().printClass();
  }

  @Lookup
  public ClassB getClassB() {
    return null;
  }
}

可以发现简洁了很多,而且不再和Spring强耦合,再次运行测试依然可以得到正确的输出。
被标注的方法的返回值不再重要,因为容器会动态生成一个子类然后将这个被注解的方法重写/实现,最终调用的是子类的方法。

使用的@Lookup的方法需要符合如下的签名:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • Windows中使用Java生成Excel文件并插入图片的方法

    Windows中使用Java生成Excel文件并插入图片的方法

    这篇文章主要介绍了Windows中使用Java生成Excel文件并插入图片的方法,其中向Excel中插入图片文中通过使用Apache POI来实现,需要的朋友可以参考下
    2016-02-02
  • java二叉树的遍历方式详解

    java二叉树的遍历方式详解

    这篇文章主要为大家详细介绍了java实现二叉树遍历的四种方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-08-08
  • MyBatis通用Mapper实现原理及相关内容

    MyBatis通用Mapper实现原理及相关内容

    今天小编就为大家分享一篇关于MyBatis通用Mapper实现原理及相关内容,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • springboot实现配置本地访问端口及路径

    springboot实现配置本地访问端口及路径

    这篇文章主要介绍了springboot实现配置本地访问端口及路径,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java实现SSH模式加密

    Java实现SSH模式加密

    这篇文章主要介绍了Java实现SSH模式加密的相关资料,需要的朋友可以参考下
    2016-01-01
  • Java中double精度丢失问题原因及解决办法

    Java中double精度丢失问题原因及解决办法

    使用Java double进行运算时,经常出现精度丢失的问题,总是在一个正确的结果左右偏0.0000**1,这篇文章主要给大家介绍了关于Java中double精度丢失问题原因及解决办法,需要的朋友可以参考下
    2024-01-01
  • Java 根据XPATH批量替换XML节点中的值

    Java 根据XPATH批量替换XML节点中的值

    这篇文章主要介绍了Java根据XPATH批量替换XML节点中的值,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • java基础之字符串编码知识点总结

    java基础之字符串编码知识点总结

    这篇文章主要介绍了java基础之字符串编码总结,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有很好的帮助,要的朋友可以参考下
    2021-04-04
  • Java调用DeepSeek API的最佳实践及详细代码示例

    Java调用DeepSeek API的最佳实践及详细代码示例

    这篇文章主要介绍了如何使用Java调用DeepSeek API,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、错误处理、测试和部署,文章还提供了代码示例和注意事项,帮助开发者顺利完成API调用,需要的朋友可以参考下
    2025-02-02
  • Java如何使用Optional与Stream取代if判空逻辑(JDK8以上)

    Java如何使用Optional与Stream取代if判空逻辑(JDK8以上)

    这篇文章主要给大家介绍了关于Java如何使用Optional与Stream取代if判空逻辑(JDK8以上)的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09

最新评论