proxyMode ScopedProxyMode.TARGET_CLASS vs ScopedProxyMode.INTERFACE

正如其他SO答案建议的那样,根据您的需要使用代理模式类型,我仍然感到困惑;

@Configuration @ComponentScan public class Application { public static void main( String[] args ) { ApplicationContext context = new AnnotationConfigApplicationContext(Application.class); PrototypeBeanFactory factoryBean = context.getBean(PrototypeBeanFactory.class); System.out.println("Let's start"); SomeInterface b1 = factoryBean.getPrototypeBeanInstance(); SomeInterface b2 = factoryBean.getPrototypeBeanInstance(); System.out.println(b1.hashCode()); System.out.println(b2.hashCode()); b1.sayHello(); b2.sayHello(); b1.sayHello(); b2.sayHello(); } } @Component public class PrototypeBeanFactory { @Lookup public PrototypeBean getPrototypeBeanInstance(){ System.out.println("It'll be ignored"); return null; } } @Component @Scope(value="prototype", proxyMode = ScopedProxyMode.INTERFACES) public class PrototypeBean { public PrototypeBean() { System.out.println("I am created"); } public void sayHello() { System.out.println("Hello from " + this.hashCode()); } } 

产量

 Let's start I am created I am created 1849201180 1691875296 Hello from 1849201180 Hello from 1691875296 Hello from 1849201180 Hello from 1691875296 

现在,如果我将代理模式更改为TARGET_CLASS

产量

 Let's start -721204056 -721204056 I am created Hello from 172032696 I am created Hello from 299644693 I am created Hello from 1771243284 I am created Hello from 2052256418 

为什么,在基于类的代理的情况下,它在每个方法调用上创建不同的对象?

 @Component @Scope(value="prototype", proxyMode = ScopedProxyMode.INTERFACES) public class PrototypeBean { ... } 

在您的情况下,这将导致每次调用getBean bean时bean,因为您的PrototypeBean没有实现接口,因此无法创建范围内的代理。 在您的情况下,您调用查找方法两次,因此您将获得2个实例。 这实际上是prototype范围bean的正常行为。

 Component @Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) public class PrototypeBean { ... } 

这将导致创建代理。 该代理创建一次,并将在每次调用getBean返回。 只要在代理上调用方法,它就会根据范围创建新方法或重用现有方法。 由于您已将范围指定为prototype每个方法调用都将生成一个新对象。

注意:如果您的类实现了一个公开适当方法的接口,则proxyMode = ScopedProxyMode.INTERFACESproxyMode = ScopedProxyMode.TARGET_CLASS proxyMode = ScopedProxyMode.INTERFACES的行为没有区别,因为在这两种情况下都会创建一个范围代理。

我用sayHello创建了一个PrototypeBeanI接口,并在main()中使用了接口,结果仍然不同。 似乎使用PrototypeBeanI或PrototypeBean作为变量类型不会产生任何差异。