1.4.6.1. Lookup Method Injection(查找方法注入)

  Spring Framework Documentation (5.3.10)

Core

IoC Container, Events, Resources, i18n, Validation, Data Binding, Type Conversion, SpEL, AOP.

   Core Technologies

1. The IoC Container

1.1. Introduction to the Spring IoC Container and Beans(Spring IoC容器和bean简介)

1.2. Container Overview (容器概览)

1.3. Bean Overview (Bean概览)

1.4. Dependencies(依赖)

1.4.1. Dependency Injection(依赖注入)

1.4.2. Dependencies and Configuration in Detail(依赖与配置详细介绍)

1.4.3. Using depends-on(使用depends-on)

1.4.4. Lazy-initialized Beans(延迟初始化Bean)

1.4.5. Autowiring Collaborators(自动装配协作者)

1.4.6. Method Injection(方法注入)

1.4.6.1. Lookup Method Injection(查找方法注入)

1.4.6.2. Arbitrary Method Replacement(任意方法替换)

1.5. Bean Scopes(Bean作用域)


下载此文档精编完整版

 No.内容下载地址文档内容目录
1中英双语精编版 第一部分PDF下载内容目录
2中英双语精编版 第二部分PDF下载内容目录
3中文精编版 第一部分PDF下载内容目录
4中文精编版 第二部分PDF下载内容目录

更多章节内容,请点击查看:  Core Technologies



关于Spring Framework Documentation (5.3.10)  核心技术的更多内容,请点击:

  Core Technologies


1.4.6.1. Lookup Method Injection(查找方法注入)

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.

查找方法注入是容器重写容器托管beancontainer-managed bean)上的方法并返回容器中另一个命名bean的查找结果的能力。查找通常涉及一个原型(prototypebean,如前一节所述(the preceding section)。Spring框架通过使用CGLIB库中的字节码生成特性来动态生成重写该方法的子类,从而实现这种方法注入。

  • For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the method to be overridden cannot be final, either.
  • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.
  • Concrete methods are also necessary for component scanning, which requires concrete classes to pick up.
  • A further key limitation is that lookup methods do not work with factory methods and in particular not with @Bean methods in configuration classes, since, in that case, the container is not in charge of creating the instance and therefore cannot create a runtime-generated subclass on the fly.

  • 对于这个动态子类来说,Spring bean容器从中生成子类的类不能(即父类)是final,要重写的方法也不能是final。
  • 对具有abstract 方法的类进行单元测试时,需要您自己对该类进行子类化,并提供abstract 方法的存根实现(stub implementation)。
  • 组件扫描(component scanning)也需要具体的方法,这需要选择具体的类(class)。
  • 另一个关键限制是,查找方法不适用于工厂方法,也不适用于配置类中的@Bean方法,因为在这种情况下,容器不负责创建实例,因此无法动态创建运行时生成的子类(runtime-generated subclass)。

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:

对于前面代码段中的CommandManager 类,Spring容器动态重写 createCommand() 方法的实现。CommandManager类没有任何Spring依赖项,如修改后的示例所示:

Java

package fiona.apple;

// no more Spring imports!

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() ;
}

Kotlin

package fiona.apple

// no more Spring imports!

abstract class CommandManager {

    fun process(commandState: Any): Any {
        // grab a new instance of the appropriate Command interface
        val command = createCommand() 
        // set the state on the (hopefully brand new) Command instance
        command.state = commandState
        return command.execute() 
    }

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

In the client class that contains the method to be injected (the CommandManager in this case), the method to be injected requires a signature of the following form:

在包含要注入的方法的客户端类(本例中为CommandManager)中,要注入的方法需要以下形式的签名:

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

If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. Consider the following example:

如果方法是abstract,则动态生成的子类(dynamically-generated subclass)将实现该方法。否则,动态生成的子类将重写在原始类中定义的具体方法。考虑下面的例子:

<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype">
    <!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
    <lookup-method name="createCommand" bean="myCommand"/>
</bean>

The bean identified as commandManager calls its own createCommand()  method whenever it needs a new instance of the myCommand bean. You must be careful to deploy the myCommand bean as a prototype if that is actually what is needed. If it is a singleton, the same instance of the myCommand bean is returned each time.

Alternatively, within the annotation-based component model, you can declare a lookup method through the @Lookup annotation, as the following example shows:

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

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

Java

public abstract class CommandManager {

    public Object process(Object commandState) {
        Command command = createCommand() ;
        command.setState(commandState);
        return command.execute() ;
    }

    @Lookup("myCommand")
    protected abstract Command createCommand() ;
}

Kotlin

abstract class CommandManager {

    fun process(commandState: Any): Any {
        val command = createCommand() 
        command.state = commandState
        return command.execute() 
    }

    @Lookup("myCommand")
    protected abstract fun createCommand() : Command
}

Or, more idiomatically, you can rely on the target bean getting resolved against the declared return type of the lookup method:

或者,更习惯地说,您可以依靠目标beantarget bean)解析查找方法的声明返回类型:

Java

public abstract class CommandManager {

    public Object process(Object commandState) {
        MyCommand command = createCommand() ;
        command.setState(commandState);
        return command.execute() ;
    }

    @Lookup
    protected abstract MyCommand createCommand() ;
}

Kotlin

abstract class CommandManager {

    fun process(commandState: Any): Any {
        val command = createCommand() 
        command.state = commandState
        return command.execute() 
    }

    @Lookup
    protected abstract fun createCommand() : Command
}

Note that you should typically declare such annotated lookup methods with a concrete stub implementation, in order for them to be compatible with Spring’s component scanning rules where abstract classes get ignored by default. This limitation does not apply to explicitly registered or explicitly imported bean classes.

请注意,您通常应该使用具体的存根实现(concrete stub implementation)声明此类带注解的查找方法(annotated lookup method),以便它们与Spring的组件扫描规则兼容,默认情况下抽象类会被忽略。此限制不适用于显式注册或显式导入的bean类。

Another way of accessing differently scoped target beans is an ObjectFactoryProvider injection point. See Scoped Beans as Dependencies.

You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) to be useful.

另一种访问不同作用域的目标beandifferently scoped target bean)的方法是ObjectFactoryProvider注入点。参考Scoped Beans as Dependencies

您还可能发现ServiceLocatorFactoryBean (在org.springframework.beans.factory.config包中)很有用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月满闲庭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值