Java Spring作用域代理为作用域代理bean字段的字段而不是bean本身工作?
这是我的代码: Spring配置:Java Spring作用域代理为作用域代理bean字段的字段而不是bean本身工作?,java,spring,proxy,Java,Spring,Proxy,这是我的代码: Spring配置: 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(base
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 {
}
傅:
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: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());
}
}
我的问题是,
据我所知,064bdb74-cad7-4d13-86fe-a4fc0021e5a0不等于c6f2d9be-09b4-456d-9414-8ECE2F2F2AC9E,因为FooImpl实际上是作用域氧
我不明白的是,为什么barOne.getFoo可以等于barTwo.getFoo
这怎么可能:
barOne.getFoo() == barTwo.getFoo()
barOne.getFoo().getState() != barTwo().getFoo().getState()
??突出显示代码:
- 代码在Singleton中使用原型范围的bean
- 然后使用bean代理模式ScopedProxyMode.TARGET_类
- 由于UUID是最终类,请参见 . 因此,尝试获取代理是不可能的,每次都会获得一个新对象
Foo
和Bar
,但这两个bean不仅仅是一个简单的实现(FooImpl和BarImpl),而是代理(CglibAopProxy)。
因此,在您的
TestClass
类中,您有两个对BarImpl
barOne和barTwo的相同AopProxy的引用。由于条形图
的作用域为单例,因此AopProxy的底层目标类与预先优化的对象(BarImpl)相同。这个Bar
AopProxy有一个类型为Foo
的注入AopPorxy,因此当您执行以下代码barOne.getFoo()==barTwo.getFoo()
时,它的计算结果为true,因为barOne
和barTwo
都有相同的AopProxy实例(不是目标类),但是当您调用barTwo时().getFoo().getState()
AopProxy正在创建目标类(FooImpl)的新实例,并对其执行getState()
方法。因此,每次调用bar.getFoo().getState()
都将创建FooImpl
的新实例,然后执行其getState()
method.奇怪的是,它怎么知道什么时候需要用新实例替换代理!如果只是在目标类上执行公共方法,它基本上不会用新实例更改代理。这就是代理的概念。如果你想知道目标是什么,代理只会从IOC获取目标,IOC只会返回新的insta你应该看到上面@Babl的答案。
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
barOne.getFoo() == barTwo.getFoo()
barOne.getFoo().getState() != barTwo().getFoo().getState()