This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

AnnouncementAnnouncement Module

Collapse

No announcement yet.

How to specify/make a bean as immutable in beanfactoryPage Title Module

How to specify/make a bean as immutable in beanfactory

Aug 17th, 2004, 03:53 PM

Hi,

I am to newbie to spring, hence pardon for any dumb questions.

I was going thru beanfactory xml and spring has a support for specifying whether a bean is singleton or prototype. I would like to know whether there is way I can say that particular bean is immutable (ex: <bean name="yetAnotherExample" class="examples.ExampleBeanTwo" immutable="true"/>and when I declare it as immutable, spring automatically uses '==' for equality (obj1 == obj2) rather than equals().
Thanks,
Jeelani

Comment

Are you puzzled about the term 'prototype'? By prototyping it is just said that everytime you call 'getBean' or refer to the bean a new instance is created according to the prototype specified by the <bean> tags.

It is not the same like query by example or anything like that.

Also you might refer to the Flyweight (/Lightweight) Pattern. By calling it immutable you might want to create only one instance for given property combination or something like that. This can be done by providing your own factory implementation. This is also fairly simple to do.

Comment

Thanks for the reply. Since when we say that singleton="true" even though the framework takes care of creating only instance, we can't prevent the user apps from modifying the values. I was looking more at
'Is there a way to tell spring that make mybean in this context immutable and singleton. If we do make the bean immutable programmatically, then I can't use the same bean in other context, where mutability is required.

I was just curious to know that whether we can inject immutable property in particular contexts by allowing the framework to create some wrapper class over the bean to make it immutable.

Thanks,
Jeelani

Comment

You can create an Advisor that throws an exception whenever a method is invoked and apply it to your singleton bean setters methods. This will prevents "accidental" properties changees. I can see, however two issues with this scenario:
1. you can not apply your Advice to public properties.
2. you can not prevent changes to "Object" properties:

Your bean will be made immutable after the bean factory has set the properties on it, but your bean class can still be used elsewhere for mutable instances while ever you don't call the setImmutable() method on it.

Comment

this is a nice solution but it does not yet prevents users from calling

Code:

MyBean.getSomeObject&#40;&#41;.setSomeProperty&#40;someValue&#41;;

correct, it was a simple answer to an incomplete set of requirements. The main point being AIUI how to prevent properties being set after the bean factory creates the bean, but without preventing other (non Spring) apps from reusing the class and setting them. In your example above, the accessor can return a clone of someObject.

Comment

maybe you were inspired by J2SE Collections.unmodifiebleSet etc. methods. Please notice that for each type of Collection there is a special method/wrapper respectively. A general wrapper can be made only using AOP. And not just the simple DynaProxy solution, but the full blown code manipulation (to disable an access to the public fields).

You have one more possibility. Define your implementing class as real immutable (no direct setters, getters returning clones or immutable collections, ...)
The bean definition can then use just constructor args.

Comment

The flexibility provided by Spring Framework is good. However, as I start introducing it into our project, my tech lead did ask me the following questions,

If it's a "spring singleton" defined in Spring Context, how do you prevent the other developers from doing a "new" manually? :?:

If it's not a "spring singleton”, again, how can you prevent people from just trying the "new" but not “getBean” from the framework? :?:

I think a constructor injection is a necessary. We are also considering making a "non-spring" singleton to access the Spring context in order to prevent this from happening.

Any other suggestion is all welcome.

I checked the documentation. The "factory method" is mainly for the purpose to define some old type of factory class to be hanlded by the Spring Context. I don't think it can solve the issue. When you provide a "getInstance" instead of "new", the same issue is still there. (in my quote)

Am I right?

The point is how do you prevent them from using a "new" or "getInstance" without using "getBean" to create the bean? Any one else here has the similar concern?

That seems a code smell, now everything is dependent on its environment. Could AOP help here? Use a constructor aspect on a classes' constructors, and this does the context origination check somehow.

Originally posted by jasonchen_nj

Let me quote myself here and open the topic again.

Originally posted by jasonchen_nj

The flexibility provided by Spring Framework is good. However, as I start introducing it into our project, my tech lead did ask me the following questions,

If it's a "spring singleton" defined in Spring Context, how do you prevent the other developers from doing a "new" manually? :?:

If it's not a "spring singleton”, again, how can you prevent people from just trying the "new" but not “getBean” from the framework? :?:

I think a constructor injection is a necessary. We are also considering making a "non-spring" singleton to access the Spring context in order to prevent this from happening.

Any other suggestion is all welcome.

I checked the documentation. The "factory method" is mainly for the purpose to define some old type of factory class to be hanlded by the Spring Context. I don't think it can solve the issue. When you provide a "getInstance" instead of "new", the same issue is still there. (in my quote)

Am I right?

The point is how do you prevent them from using a "new" or "getInstance" without using "getBean" to create the bean? Any one else here has the similar concern?