Область проксимального режима — проксимальный режим.TARGET_CLASS против ScopedProxyMode.ИНТЕРФЕЙС

#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 в качестве типа переменной не создает никакой разницы.