这是我的代码:
SpringConfiguration:
package biz.tugay;
/* User: koray@tugay.biz Date: 25/12/15 Time: 19:30 */
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "biz.tugay")
public class SpringConfiguration {
}
富:
package biz.tugay;
/* User: koray@tugay.biz Date: 25/12/15 Time: 19:36 */
public interface Foo {
String getState();
}
FooImpl:
package biz.tugay;
/* User: koray@tugay.biz Date: 25/12/15 Time: 19:31 */
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class FooImpl implements Foo {
private final String state = UUID.randomUUID().toString();
public String getState() {
return state;
}
}
栏:
package biz.tugay;
/* User: koray@tugay.biz Date: 25/12/15 Time: 19:35 */
public interface Bar {
Foo getFoo();
}
BarImpl:
package biz.tugay;
/* User: koray@tugay.biz Date: 25/12/15 Time: 19:33 */
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(value = "singleton")
public class BarImpl implements Bar {
private Foo foo;
@Autowired
public void setFoo(Foo foo) {
this.foo = foo;
}
public Foo getFoo() {
return foo;
}
}
和测试类:
package biz.tugay;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static java.lang.System.out;
public class TestClass {
final static Class<SpringConfiguration> SPRING_CONFIGURATION_CLASS = SpringConfiguration.class;
public static void main(String[] args) {
final ApplicationContext applicationContext;
applicationContext = new AnnotationConfigApplicationContext(SPRING_CONFIGURATION_CLASS);
final Bar barOne = applicationContext.getBean(BarImpl.class);
final Bar barTwo = applicationContext.getBean(BarImpl.class);
out.println("barOne == barTwo: " + (barOne == barTwo));
out.println("barOne.getFoo == barTwo.getFoo: " + (barOne.getFoo() == barTwo.getFoo()));
out.println(barOne.getFoo().getState());
out.println(barTwo.getFoo().getState());
}
}
输出将是:
barOne == barTwo: true
barOne.getFoo == barTwo.getFoo: true
064bdb74-cad7-4d13-86fe-a4fc0021e5a0
c6f2d9be-09b4-456d-9414-8ece2f2acc9e
我的问题是,
我知道064bdb74-cad7-4d13-86fe-a4fc0021e5a0不等于c6f2d9be-09b4-456d-9414-8ece2f2acc9e,因为FooImpl实际上是ScopedProxy。
我不明白的是,为什么barOne.getFoo可以等于barTwo.getFoo?
这怎么可能:
barOne.getFoo() == barTwo.getFoo()
barOne.getFoo().getState() != barTwo().getFoo().getState()
???
答案 0 :(得分:3)
首先要解释输出,你需要了解Spring框架的工作方式和内容。让我们开始的想法,当你注射&#34;短暂的&#34;范围豆成为一个长寿的&#34; scope bean(在你的情况下是原型bean到singleton bean)Spring注入一个AOP代理来代替scoped bean。
也就是说,您需要注入一个代理对象,该对象公开与范围对象相同的公共接口,但也可以从相关范围(例如HTTP请求)中检索真实目标对象,并将方法调用委托给实际对象
基本上,JDK代理和CGLIB代理有两种主要的代理类型(默认)。
让我们回到示例代码并尝试了解发生了什么......
当您的应用程序启动时,Spring Framework会创建两个bean Foo
和Bar
,但这两个bean不仅仅是一个简单的实现(FooImpl和BarImpl),而是代理(CglibAopProxy&#39; s)。
所以在你的TestClass
课程中,你有2个引用同一个{0}的AopProxy barOne和barTwo。由于BarImpl
的范围是单例,因此AopProxy的底层目标类是预先加入的同一对象(BarImpl)。此Bar
AopProxy注入的AopPorxy类型为Bar
,因此当您执行以下代码Foo
时,其评估为true,因为barOne.getFoo() == barTwo.getFoo()
和barOne
具有相同的AopProxy实例(不是目标类),但是当您调用barTwo
时,AopProxy正在创建目标类的新实例(FooImpl)并在其上执行barTwo().getFoo().getState()
方法。因此,每次调用getState()
都会创建bar.getFoo().getState()
的新实例,然后执行其FooImpl
方法。
答案 1 :(得分:0)
代码突出显示:
结果是预期的。为什么呢?