1. Method Injection
In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container creates the singleton bean A only once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed.
在大多数应用场景中,容器中的大多数 bean 是单例的。 当单例 Bean 需要与另一个单例 Bean 协作或非单例 Bean 需要与另一个非单例 Bean 协作时,通常可以通过将一个 Bean 定义为另一个 Bean 的属性来处理依赖性。 当 bean 的生命周期不同时会出现问题。 假设单例 bean A 可能需要使用非单例(原型)bean B,也许是在 A 的每个方法调用上使用。容器仅创建一次单例 bean A,因此只有一次机会来设置属性。 每次需要一个容器时,容器都无法为 bean A 提供一个新的 bean B 实例。
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.
一个解决方案是放弃某些控制反转。 您可以通过实现 ApplicationContextAware
接口,并通过对容器进行 getBean("B")
调用来使 bean A 知道该容器,以便每次 bean A 需要它时都请求一个(通常是新的)bean B 实例。
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.
查找方法注入是容器覆盖容器管理的 Bean 上的方法并返回容器中另一个命名 Bean 的查找结果的能力。 查找通常涉及原型 bean,如上一节中所述。Spring 框架通过使用从 CGLIB 库生成字节码来动态生成覆盖该方法的子类来实现此方法注入。
2. 核心代码
代码已经上传至 https://github.com/masteryourself-tutorial/tutorial-spring ,详见
tutorial-spring-framework/tutorial-spring-framework-injection-lookup
工程
1. Dog
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Dog {
}
2. Person
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
@ToString
public class Person {
/**
* 会带来因为作用域范围引出的问题
*/
@Autowired
private Dog dog;
/**
* 使用 {@link Lookup} 避免原型问题
*
* @return
*/
@Lookup
public Dog dog() {
return null;
}
public void doSomething() {
System.out.println("使用 @Autowired:" + dog.hashCode());
System.out.println("使用 @Lookup:" + dog().hashCode());
}
}