Spring中引入Lookup注解的作用是什么

发布时间:2021-01-15 17:14:51 作者:Leah
来源:亿速云 阅读:421

本篇文章为大家展示了Spring中引入Lookup注解的作用是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

ApplicationContextAware接口

官方文档首先也提到了一个解决方案就是把A弄成容器的Aware( make bean A aware of the container),也就是实现ApplicationContextAware接口。

A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows this approach

文档里随后就提供了一个示例来说明这个解决方案如何做。

// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {
 private ApplicationContext applicationContext;
 public Object process(Map commandState) {
  // grab a new instance of the appropriate Command
  Command command = createCommand();
  // set the state on the (hopefully brand new) Command instance
  command.setState(commandState);
  return command.execute();
 }
 protected Command createCommand() {
  // notice the Spring API dependency!
  return this.applicationContext.getBean("command", Command.class);
 }
  public void setApplicationContext(
   ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = applicationContext;
 }
 }

虽然解决了一开始提出的问题,但是Spring随后就说到:

The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, lets you handle this use case cleanly.

也就是说 前面的方法是不可取的,因为业务代码知道并耦合到Spring框架。那怎么降低这个耦合度呢?后半句就给出了答案:方法注入是Spring IOC容器的一个稍微高级的特性,它允许您干净地处理这个用例。

Lookup Method方法注入

首先再次引入官方文档中的阐述:

Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container. The lookup typically involves a prototype bean, as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method.

简要概括下这段话有三个意思:

使用Lookup方式需要注意以下几点:

这段话也可以概括为以下几点:

  1. 使这个动态子类可以用,这个类不能是final,要重写的方法也不能是final。

  2. 单元测试具有抽象方法的类需要您自己对该类进行子类化,并提供抽象方法的存根实现。

  3. 具体的方法对于组件扫描也是必要的,这需要具体的类来获取。

  4. 一个关键限制是Lookup方法不适用于工厂方法,尤其是配置类中的@Bean方法,因为在这种情况下,容器不负责创建实例,因此不能动态创建运行时生成的子类。

接下来Spring就拿上面本来基于ApplicationContextAware的方法来说,就可以用Lookup来替换了。对于前面代码段中的CommandManager类,Spring容器动态重写createCommand()方法的实现。CommandManager类没有任何Spring依赖项,如修改后的示例所示

In the case of the CommandManager class in the previous code snippet, the Spring container dynamically overrides the implementation of the createCommand() method. The CommandManager class does not have any Spring dependencies, as the reworked example shows.

Xml配置lookup-method

 public abstract class CommandManager { 
  public Object process(Object commandState) {
   // grab a new instance of the appropriate Command interface
   Command command = createCommand();
   // set the state on the (hopefully brand new) Command instance
   command.setState(commandState);
   return command.execute();

 }
 // okay... but where is the implementation of this method?
  protected abstract Command createCommand();
 }

在包含要注入的方法的CommandManager类中,要注入的方法需要以下形式的签名:

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

如果方法是抽象的,则动态生成的子类将实现该方法。否则,动态生成的子类将重写在原始类中定义的具体方法。

我们来看下Bean的配置:

当需要myCommand这个Bean的新实例时,被标识为commandManager的bean就会调用自己的createCommand()方法。如果需要的话,必须小心地将myCommand 这个bean部署为原型。如果是单例,则每次都返回相同的myCommand bean实例.

@Lookup注解

在基于注解的组件模型中,可以通过@lookup注释声明查找方法,如下例所示

 public abstract class CommandManager {
  public Object process(Object commandState) {
   Command command = createCommand();
   command.setState(commandState);
   return command.execute();
  }
  @Lookup("myCommand")
  protected abstract Command createCommand();
 }

或者,你也可以依靠目标bean根据lookup方法的声明返回类型进行解析

public abstract class CommandManager {
  public Object process(Object commandState) {
   MyCommand command = createCommand();
   command.setState(commandState);
   return command.execute();
  }
  @Lookup
  protected abstract MyCommand createCommand();
 }

需要注意的是你通常应该用一个具体的存根实现声明这种带注解的查找方法,以便它们与Spring的组件扫描规则兼容,默认情况下抽象类会被忽略。此限制不适用于显式注册或显式导入的bean类。也就是说如果用组件扫描Bean的话因为抽象类默认是被忽略的,但是你加上这个Lookup注解后就不会呗忽略。

Spring在最后也提供了其他两种解决思路:

Another way of accessing differently scoped target beans is an ObjectFactory/ Provider injection point. See Scoped Beans as Dependencies。You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful.

  1. 通过ObjectFactory或者ObjectProvider.

  2. 通过ServiceLocatorFactoryBean.

上述内容就是Spring中引入Lookup注解的作用是什么,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. Spring中@Conditional注解的原理是什么
  2. Spring中@RestControllerAdvice注解的原理是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

spring lookup

上一篇:pycharm中复制一行的快捷键是什么

下一篇:mysql左连接与内连接的区别是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》