#java #spring
#java #весна
Вопрос:
Как предлагали другие ответы 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
Почему в случае прокси-сервера на основе классов он создает разные объекты при каждом вызове метода?
Ответ №1:
@Component
@Scope(value="prototype", proxyMode = ScopedProxyMode.INTERFACES)
public class PrototypeBean { ... }
Это, в вашем случае, приведет к bean для каждого вызова getBean
bean, поскольку ваш PrototypeBean
не реализует интерфейс, и поэтому ограниченный прокси-сервер не может быть создан. В вашем случае вы дважды вызываете метод поиска и, следовательно, получите 2 экземпляра. На самом деле это нормальное поведение prototype
компонента с ограниченной областью.
Component
@Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class PrototypeBean { ... }
Это приведет к созданию прокси. Этот прокси создается один раз и будет возвращаться при каждом вызове getBean
. Как только вы вызываете метод на прокси, он, в зависимости от области видимости, либо создаст новый, либо повторно использует существующий. Поскольку вы указали область действия, поскольку prototype
каждый вызов метода приведет к новому объекту.
Примечание: Если ваш класс будет реализовывать интерфейс, который предоставляет соответствующий метод, не будет никакой разницы в поведении proxyMode = ScopedProxyMode.INTERFACES
и proxyMode = ScopedProxyMode.TARGET_CLASS
, поскольку в обоих случаях будет создан прокси-сервер с ограниченной областью действия.
Ответ №2:
Я создал прототип интерфейса Beani с помощью sayHello и использовал интерфейс в main(), все еще разные результаты. кажется, что использование PrototypeBeanI или PrototypeBean в качестве типа переменной не создает никакой разницы.