As far as I read from spring documentation, if I put a prototype scoped bean inside a larger scoped bean, prototype scoped bean acts like as if it is also a view scoped bean. Meaning, it will only be initialized when the container bean is initialized.
In my prototype scoped bean, I have a simple property and a getter setter for that.
@Repository
@Transactional( readonly=true )
@MyPrototypeScope // see definition of this one at [1]
class MyPrototypeScopedBean {
protected String member ;
public String getMember( ) { return this.member ; }
public void setMember( String member ) {
this.member = member ;
System.err.println( "member is set to " + this.member + ", class is : "
+ this.getClass( ).getName( ) ) ;
}
protected void someMethod( ) {
System.err.println( "The member is " + member + ", class is : "
+ this.getClass( ).getName( ) ) ;
}
}
My view scoped bean autowires it and tries to use it.
class MyViewScopedBean {
@Autowired
MyPrototypeScopedBean proto ;
....
public void problematicMethod( ) {
MyPrototypeScopedBean tmpReference = this.proto ; // to be sure we access it only once
tmpReference.setMember( "X" ) ;
System.err.println( "Value of member is " + tmpReference.getMember( ) + ", class is : "
+ this.getClass( ).getName( ) ) ;
this.proto.someMethod( ) ;
}
}
In the above case, I expect to see an output like below:
member is set to X, class is : com.xxx.MyPrototypeScopedBean$$EnhancerBySpringCGLIB$$xxxxxx
Value of member is X, class is : com.xxx.MyPrototypeScopedBean
The member is X, class is : com.xxx.MyPrototypeScopedBean
But instead, what I see is similar to below:
member is set to X, class is : com.xxx.MyPrototypeScopedBean$$EnhancerBySpringCGLIB$$xxxxxx
Value of member is null, class is : com.xxx.MyPrototypeScopedBean
The member is null, class is : com.xxx.MyPrototypeScopedBean
As if, spring somehow gives me a fresh instance for each reference of the "proto", be it a member access or a method call.
My code is obviously more complicated than this, but this is what the design is supposed to do. So, my question is, am I expecting something wrong? Is there any configuration issues that could cause this problem? Or this is just a symptom of a bug in some place else?
thank you.
Update 1:
Following the suggestion of skaffman
, I have added the class names, at the end of println statements. Code and outputs are updated to reflect the changes.
Also added the scope definitions on the bean.
[1]
@Target( { ElementType.TYPE, ElementType.METHOD } )
@Retention( RetentionPolicy.RUNTIME )
@Documented
@Scope( BeanDefinition.SCOPE_PROTOTYPE )
public @interface MyPrototypeScope {
ScopedProxyMode proxyMode( ) default ScopedProxyMode.TARGET_CLASS ;
}