|
#1
|
|||
|
|||
|
Hi,
I'm currently refactoring a large Swing application to use the Spring Framework. Unfortunately, the application currently makes heavy use of the Singleton "anti-pattern" to access the business service layer. So far, it has been easy to make the IOC container instantiate the service layer objects as beans and to inject them into objects at the "top layer" of the application, that is objects directly involved with the main frame. However, what about objects farther down the food chain? For example (somewhat contrived), what about a model object for a panel that is part of another panel on a dialog that is accessed from a child frame of the main frame? The dependency chain could look like this, for example: Code:
MainFrame ->ChildFrame ->DialogLaunchedFromChildFrame ->BigPanelOnDialog ->LittlePanelInsideBigPanel ->LittlePanelModel ->MyServiceLayerObject Code:
MyServiceLayerObject.getInstance.doSomeService() 1) Instantiate ALL of the objects in the IOC container and use dependency injection to inject the service layer dependency into LittlePanelModel. This may seem like the logical choice except when you look at the big picture. This sort of long dependency chain is seen all over the application because there are many, many screens, dialogs and panels in the app. I would have to configure several hundred objects in the application context configuration files. Some of you say "what's wrong with that"? In the long run, I think it might be workable but in the short run, I can only refactor this app in stages. I can't make all of the beans IOC-managed all at once; I have to move towards this goal slowly. 2) Get the container to Inject the dependency into MainFrame and then pass the dependency along as each object instantiates its helper object in the next link of the dependency chain. I don't particularly like this because objects in the middle of the chain are not directly dependent on the service layer objects; to keep coupling low, I don't want to introduce unnecessary dependencies. 3) Use "one singleton to rule them all" (this hiliarious Lord of the Rings-ish quote is from the javadocs for Spring's BeanFactoryBootstrap class). In other words, allow singleton access to the bean factory or application context that holds all of the service layer objects. This is still a singleton but at least there's only ONE singleton in the entire app instead of one for each service object. Comments or advice?
__________________
Cheers, Joe "All your bean are belong to us" - Spring Framework's IOC Container |
|
#2
|
|||
|
|||
|
I think maybe option 3 okay for Swing application. I looking at Spring Rich Client and they have this sort of "one singleton to rule all". It is Application class. If you looking at some Spring Rich Client code, you see lots of classes access this singleton to look up images, icons, rules source, messages, etc. Example:
- Application.services().getIconSource() in OverlayValidationInterceptorFactory class - Application.services() in ApplicationServicesAccessor class, which many class derives from and using it to get images, icons, etc. So I think is not big deal if Keith already doing this in Spring Rich Client (if Keith using it, it must be okay for you to use it too :wink: ). Maybe just make sure you have only this one singleton though. Make everything else non-singleton. What you other guys say about this one?
__________________
Stefano Rossi "If I want your opinion, I'll give it to you." |
|
#3
|
|||
|
|||
|
Quote:
Does anyone else have a differing opinion?
__________________
Cheers, Joe "All your bean are belong to us" - Spring Framework's IOC Container |
|
#4
|
|||
|
|||
|
Not that I'm criticizing this idea, but how is this not replacing the "singleton" antipattern with the the ServiceLocater "anti-pattern"?
A matter of degree or misuse? Or is a ServiceLocator object that is created via DI better then an old style ServiceLocator. I guess if you dig deep into any code base (or even cosmology) there is one singleton somewhere.
|
|
#5
|
|||
|
|||
|
jbetancourt, thanks for your response.
Quote:
1) The custom singletons can be converted to "service" beans and we can remove the getInstance() method from each bean. This means that classes that depend on them can now depend on their interfaces instead of their implementations (e.g. you can call myService.someMethod() instead of myServiceImpl.getInstance().someMethod()). This makes it easier to change the implementation or to mock it up for testing. 2) The properties of these service beans can all be configured in a standard way in the IOC container instead of using ad hoc techniques. 3) These service beans can be injected with their dependencies (for example, dependencies on a transaction manager) by the IOC container. Quote:
Quote:
In a web app, I guess you don't really need a singleton like Spring Rich Client's Application singleton. But then again, web apps have the servlet context where you can shove your app context, making it pretty much globally accessible. With Swing apps, you don't have the benefit of a servlet context. So, the way I see it, the Application singleton is sort of like the servlet context. If our existing app used only Spring Rich Client's Form, View and Dialog related classes, we would probably never see references to the Application singleton in our app's code. Unfortunately, we currently have our own "form", "view" and "dialog" framework in our existing app. At the moment, we don't have time to convert the entire app over to using Spring Rich Client's Form, View and Dialog framework. Therefore, in the short term, I think we must use the Application singleton in our framework to look up messages, icons, rules, etc in a similar fashion to how Spring Rich Client's Form, View and Dialog framework does these lookups. I don't really see the difference between what we are doing and what Spring Rich Client does. In theory, I think pure DI would be great but how do I get from here (lots of custom singletons) to there (pure DI) with the least amount of disruption to the existing app? Surely some DI is better than no DI. I think a lot Spring users are in this same situation of having to convert an existing app instead of starting from scratch. All I'm looking for is a little advice on how to do this conversion sanely without having to turn the existing app upside down all at once.
__________________
Cheers, Joe "All your bean are belong to us" - Spring Framework's IOC Container |
|
#6
|
|||
|
|||
|
cyboc,
I had to do something very similar (albeit a web app). Everything was looked up via a static factory/registry. My refactoring strategy was to start at the bottom layer by converting the factory to acquire beans from the Spring container. That let the codebase remain stable while I built up the bean configurations. In other words, the first set of beans provided by the factory came from the IoC container, but they themselves still did DL of their collaborators. At that point I began modifying those classes to replace the DL with DI. Once that was complete, I continued by moving up layer by layer. Going from the top down, you have to watch that everyone gets the same instance of your singleton since the one used by Spring is only one by virtue of the IoC registry. I may have been wrong, but I thought it would be more problemmatic during a long, complicated refactor. This is probably a good discussion for the architecture forum. We need an "Introduce Spring" refactoring with a one button Eclipse plugin. Cheers.
__________________
Randy |
![]() |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Problem with stylesheet in acegilogin.jsp page | wolf | Spring Security | 11 | Jun 1st, 2006 04:30 PM |
| after login redirects incorrectly | ryan.tyer | Spring Security | 1 | Oct 10th, 2005 05:16 PM |
| EHCaching Hibernate | dencamel | Data Access | 3 | Sep 6th, 2005 09:03 PM |
| Loosing my SecureContext | sklakken | Spring Security | 3 | Jul 21st, 2005 01:44 PM |
| DefaultAdvisorAutoProxyCreator skipping beans | youngm | Core Container | 6 | Apr 12th, 2005 04:29 PM |