欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-17 23:25:22
前言 本文主要给大家介绍了关于spring中lookup(方法注入)的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 在使用spring时,可...

前言

本文主要给大家介绍了关于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);

总结

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

上一篇:

下一篇: