Amit Kumar Gupta
Amit Kumar Gupta

Reputation: 7413

proxyMode ScopedProxyMode.TARGET_CLASS vs ScopedProxyMode.INTERFACE

As other SO answers suggested, use proxy mode type as per your need, I am still confused;

@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());
    }

}

Output

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

Now if I change the proxy-mode to TARGET_CLASS

Output

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

Why, in case of class based proxy, it creates different object on each method invocation?

Upvotes: 9

Views: 22916

Answers (2)

gli00001
gli00001

Reputation: 701

I created an interface PrototypeBeanI with sayHello and used the interface in the main(), still different results. seems that using PrototypeBeanI or PrototypeBean as the variable type does not create any difference.

Upvotes: 0

M. Deinum
M. Deinum

Reputation: 125232

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

This, in your case, will lead to a bean per invocation of getBean bean as your PrototypeBean doesn't implement an interface and as such a scoped proxy cannot be created. In your case you call the lookup method twice and hence you will get 2 instances. This is actually the normal behavior of a prototype scoped bean.

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

This will lead to the creation of a proxy. That proxy is created once and will be returned for each call to getBean. As soon as you invoke a method on the proxy it will, based on the scope, either create a new one or reuse an existing one. As you have specified the scope as prototype each method invocation will lead to a new object.

Note: If your class would implement an interface which exposes the appropriate method, there would be no difference in the behavior of proxyMode = ScopedProxyMode.INTERFACES and proxyMode = ScopedProxyMode.TARGET_CLASS as in both cases a scoped proxy would be created.

Upvotes: 21

Related Questions