Spring loosely coupled example
The object-oriented is a good design to break your system into a group of reusable objects. However, when system grows large, especially in Java project, the huge objects dependencies will always tightly coupled and causing the objects very hard to manage or modify. In this scenarios, you can use Spring framework to act as a central module to manage all the object dependencies easily and efficiently.
Output Generator Example
Let see an example, assume your project has a function to output the content to Csv or Json format. Your code may look like following:
File : IOutputGenerator.java – An interface for output generator
package com.mkyong.output; public interface IOutputGenerator { public void generateOutput(); }
File : CsvOutputGenerator.java – A Csv output generator to implement the IOutputGenerator interface.
package com.mkyong.output.impl; import com.mkyong.output.IOutputGenerator; public class CsvOutputGenerator implements IOutputGenerator { public void generateOutput(){ System.out.println("Csv Output Generator"); } }
File : JsonOutputGenerator.java – A Json output generator to implement the IOutputGenerator interface.
package com.mkyong.output.impl; import com.mkyong.output.IOutputGenerator; public class JsonOutputGenerator implements IOutputGenerator { public void generateOutput(){ System.out.println("Json Output Generator"); } }
See few ways to call the IOutputGenerator, and how to use Spring to avoid objects to coupled tightly with each other.
1. Method 1 – Call it directly
Normal way, call it directly.
package com.mkyong.common; import com.mkyong.output.IOutputGenerator; import com.mkyong.output.impl.CsvOutputGenerator; public class App { public static void main( String[] args ) { IOutputGenerator output = new CsvOutputGenerator(); output.generateOutput(); } }
Problem
In this way, the problem is the “output” is coupled tightly to CsvOutputGenerator, every change of output generator may involve code change. If this code is scatter over all of your project, every change of the output generator will make you suffer seriously.
Method 2 – Call it with helper class
You may think of create a helper class to move all the output implementation inside.
package com.mkyong.output; import com.mkyong.output.IOutputGenerator; import com.mkyong.output.impl.CsvOutputGenerator; public class OutputHelper { IOutputGenerator outputGenerator; public OutputHelper(){ outputGenerator = new CsvOutputGenerator(); } public void generateOutput(){ outputGenerator.generateOutput(); } }
Call it via helper class.
package com.mkyong.common; import com.mkyong.output.OutputHelper; public class App { public static void main( String[] args ) { OutputHelper output = new OutputHelper(); output.generateOutput(); } }
Problem
This look more elegant, and you only need to manage a single helper class, however the helper class is still tightly coupled to CsvOutputGenerator, every change of output generator is still involve minor code change.
Method 3 – Spring
In this scenario, Spring Dependency Injection (DI) is a good choice. The Spring can make your output generator loosely coupled to the output generator.
Minor change in OutputHelper class.
package com.mkyong.output; import com.mkyong.output.IOutputGenerator; public class OutputHelper { IOutputGenerator outputGenerator; public void generateOutput(){ outputGenerator.generateOutput(); } public void setOutputGenerator(IOutputGenerator outputGenerator){ this.outputGenerator = outputGenerator; } }
Create a Spring bean configuration file and declare all the your Java object dependencies here.
<!-- Spring-Common.xml --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="OutputHelper" class="com.mkyong.output.OutputHelper"> <property name="outputGenerator" ref="CsvOutputGenerator" /> </bean> <bean id="CsvOutputGenerator" class="com.mkyong.output.impl.CsvOutputGenerator" /> <bean id="JsonOutputGenerator" class="com.mkyong.output.impl.JsonOutputGenerator" /> </beans>
Call it via Spring
package com.mkyong.common; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mkyong.output.OutputHelper; public class App { public static void main( String[] args ) { ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"Spring-Common.xml"}); OutputHelper output = (OutputHelper)context.getBean("OutputHelper"); output.generateOutput(); } }
Now, you just need to change the Spring XML file for a different output generator. When output changed, you need to modify the Spring XML file only, no code changed, means less error.
Conclusion
With Spring framework – Dependency Injection (DI) is a useful feature for the object dependencies management, it is just elegant, highly flexible and easy for maintainability, specially in large Java project.
[...] to the code whereas loosely coupled requires changes to the configuration files. A good example Spring loosely coupled example Reply With Quote + Reply to Thread « Why actions in url? | – [...]
Hi Mkyong,
Thanks for explaining spring programaticaly which one I was looking for long time.
I think you have missed one return time in the Helper class.Could you please look into that.Here is the code.
Thanks,
Shyam
Sorry, i don’t get you?
This is a Constructor, which does not return.
Hi Mkyong,
Great posts! I found explainations are to the point, no verbose. great resource for young developers.
I appreciate your selfless effort
sharing is one of the great way to improve
Can you provide material about web services…thank you.
greatfull tutorial.
I’m very happy to meet this one.
thank’s you very mutch
Hi Mkyong,
Nice tutorial, Thanks.
Hi..
This is why I haven’t touched Spring from the beginning it came out but now I got no choice since a project is required me to use it.
If we compare method 2 and method 3 above, actually the work load is the same. Both still have to do modification. Method 3 doesn’t need to change the code, but still need to change the XML. It’s more or less shifting the work to XML. And worse, the tightly coupled problem that we want to get rid of is now at the XML. So what’s the advantage? As the matter of fact, now we have added one more layer (Spring) which means more works, more memory, more CPU power, and more possible bugs introduced. And then when the project grows big, the XML file would be hard to be managed.
Just my 2 cents… care to share your view?
p.s. Btw, thanks for the tutorials. Still going thru them as of this msg is being posted.
Dependency injection (DI) is a design pattern, that’s used to solve the common tightly components coupled issue, just Spring make DI very easy to implement.
In a large project or multiple developers involved, the best practice is always provide the interface to the client, so that any changes in the implementation class will not required to change at client side as well.
In method 2, if you want to change the outputGenerator, you have to modify the helper class, and any code changed may causing some new potential bugs as well (especially for junior developer). The best practice is always minimal the code change as little as possible, avoid is better. Furthermore, when the helper class grow bigger, not every developer has enough confident to make a simple change and commit the code
In method 3, if you want to change the outputGenerator, you can just create a new implementation class and inject into your interface via XML, no code is modified, and you can roll back your code easily. The work load may be similar, but the flexibility and maintainability should take it into consideration as well. For anti-XML person, can use Spring annotation to auto wire the implementation class as well.
“added one more layer (Spring) which means more works, more memory, more CPU power, and more possible bugs introduced”
More work at initial development, but less work in future. More memory or CPU power, may be, but for years of Spring development, i just do not feel there are any serious performance impact. More bugs? Definitely no, Spring is a mature and successful framework, there shouldn’t any critical bug itself, it’s more on how developer using it.
“And then when the project grows big, the XML file would be hard to be managed.”
. In addition, when project grow big, so does helper class, often times, you just do not wish to change a single line of a “big” class. Let say, your senior is left company, you have to take over his job, will you rather make change in a unknown “big” class or make a single change in XML file? Just an example.
When the project grow big, you may more harder to find your helper class
During initial development, you may feel why you need to use Spring? why added one more layer? The benefits will be obvious when the user requirement is keep changing (It’s always, if you are in agile development, even in waterfall, sad…) or doing maintainace in future.
Hope my scenarios are not misleading or confuse you
, try consult the Spring’s book titled “Spring Recipe” for more Spring explanation. Hope help.
Good Discussion on Spring IOC . Clears my doubts .
[...] Spring loosely coupled example An output generator example to develop with 3 methods, call it directly, via helper class and via Spring framework. See the different among these three methods and how Spring framework make it loosely coupled. [...]
[...] Spring loosely coupled example | Spring [...]