Reputation: 597016
As I already have application.properties
, where the database connection settings are defined, I decided it is good to put my application-specific settings in that file too. A step further - as spring reads those properties, I declared my Settings
bean as follows
<bean name="settingsBean" class="com.tickets.constants.Settings">
<property name="settings">
<props>
<prop key="backup.dir">${backup.dir}</prop>
<prop key="smtp.host">${smtp.host}</prop>
</props>
<property>
</bean>
Now, it happens sometimes, that I need some of those properties in classes that aren't directly in the spring context. Yes - I can either get the spring context from my web application context, or pass the settings as a method parameter to the utility classes, but here's my alternative approach (this is the Settings
class):
private static Properties staticSettings;
@PostConstruct
public void init() {
// making the settings available for static access
staticSettings = settings;
}
Now, this looks a bit wrong. But I can't think of a strong reason for not using it. So to formulate the question - is there any reason not to use my approach, and is there a better one.
Upvotes: 1
Views: 2879
Reputation: 403441
You're right, your solution "feels" wrong - the interaction of statics and instance looks like an anti-pattern, but it's a bit of a slippery one to get a grip on.
My gut feeling would be to push the statics a bit further, and make the class itself more internally-consistent, without sacrificing the Spring integration:
public class Settings {
private static Settings instance;
public static Settings initialise(Properties settings) {
instance = new Settings(settings);
return instance;
}
public static Settings get() {
return instance;
}
private final Properties settings;
private Settings(Properties settings) {
this.settings = settings;
}
public String getProperty(String key) {
return settings.getProperty(key);
}
}
Your Spring config would then use factory-method="initialise"
rather than the constructor, and other code can use the static get()
method to retrieve the singleton. You avoid duplication of the Properties
object, and while the static singleton is a bit of an anti-pattern itself, the code makes rather more sense.
But that's the best I can come up with on a freezing cold Saturday morning :)
Upvotes: 1
Reputation: 8446
This is a good question, and I hope you get several informed and well-reasoned responses (better than the one I expect I'm writing).
The reasons for not using this approach are the same as for adopting the Spring framework in the first place: inversion of control, loose coupling, etc. That said, I feel that if you've considered those points in this context and nevertheless feel that this approach elegantly satisfies your actual needs, go right ahead.
Sometimes I feel that Spring -- indeed many leading frameworks & techniques -- allow themselves to slip into "my way or the highway" API design, where the only way to overcome the limitations of Spring is with more Spring.
It shouldn't be that way. You should be able to adopt a thing like Spring in an existing project without signing up to re-architect every bit of your app.
And in fact there are 365236 ways (yours in one) to share objects between the Spring and non-Spring worlds. There's no technical limitation; but the zealots will give you grief.
Upvotes: 0