当前位置: 移动技术网 > IT编程>开发语言>Java > 深入理解Spring中的Lookup(方法注入)

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

2019年07月19日  | 移动技术网IT编程  | 我要评论

前言

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

总结

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网