What is AOP, Dependency Injection and Inversion Of Control in Simple English What is AOP, Dependency Injection and Inversion Of Control in Simple English spring spring

What is AOP, Dependency Injection and Inversion Of Control in Simple English


I understand your confusion and it took me some time to understand how these concepts were related together. So here is my (somehow personal) explanation of all this:

1. Inversion of Control

Inversion of control is a design principle rather generic that refers to the decoupling of the specification of a behavior from when it is actually executed. Compare for instance,

myDependency.doThis();

with

myDependency.onEventX += doThis();

In the latter, there is no direct invocation which is more flexible. In its general form, inversion of control relates to the observer pattern, events, or callbacks.

2. Dependency inversion

Dependency inversion is another design principle. Roughly speaking, it says that higher-level abstraction should not depend directly on lower-level abstractions; this results indeed in a design where higher-level abstraction can not be reused without the lower-level abstractions.

 class MyHighLevelClass {     MyLowLevelClass dep = new MyLowLeverClass(); } class App {     void main() {  new HighLevelClass().doStuff(); } }

Here, MyHighLevelClass can not compile without access to MyLowLevelClass. To break this coupling, we need to abstract the low level class with an interface, and remove the direct instantiation.

class MyLowLevelClass implements MyUsefulAbstraction { ... }class MyHighLevelClass {    MyUsefulAbstraction dep;    MyHighLevelClass( MyUsefulAbstraction dep ) {        this.dep = dep;    }}class App {     void main() {  new HighLevelClass( new LowLevelClass() ).doStuff(); } }

Note that you don't need anything special like a container to enforce dependency inversion, which is a principle. A good reading is The Dependency Inversion Principle by Uncle Bob.

3. Dependency injection

Now comes dependency injection. To me dependency injection = IoC + dependency inversion:

  1. dependencies are provided externally so we enforce the dependency inversion principle
  2. the container sets the dependencies (not us) so we speak of inversion of control

In the example I provided above, dependency injection can be done if a container is used to instantiate objects and automatically inject the dependency in the constructor (we speak then frequently of DI container):

 class App {     void main() {  DI.getHighLevelObject().doStuff(); } }

Note that there are various form of injections. Note also that under this perspective, setter injection can be seen as a form of callback -- the DI container creates the object then calls back the setter. The flow of control is effectively inverted.

4. AOP

Strictly speaking, AOP has little to do with the 3 previous points. The seminal paper on AOP is very generic and present the idea of weaving various sources together (possibly expressed with different languages) to produce a working software.

I won't expand more on AOP. What is important here, is that dependency injection and AOP do effectively plays nicely together because it makes the weaving very easy. If an IoC container and dependency injection is used to abstract away the instantiation of objects, the IoC container can easily be used to weave the aspects before injecting the dependencies. This would otherwise requires a special compilation or a special ClassLoader.

Hope this helps.


Dependency injection was explained very well in How to explain dependency injection to a 5-year-old?:

When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesn't want you to have. You might even be looking for something we don't even have or which has expired.

What you should be doing is stating a need, "I need something to drink with lunch," and then we will make sure you have something when you sit down to eat.

AOP - Aspect Oriented Programming - basically means that the source you write is modified with other code, based on rules located ELSEWHERE. This means that you can e.g. say "as the first line of every method I want a 'log.debug("entering method()")' in a central place and each and every method you compile with that rule in place will then have that line included. The "aspect" is the name of looking on code in other ways than simply from first source line to last.

Inversion of Control basically means that you do not have a central piece of code controlling everything (like a giant switch in main()) but have a lot of pieces of code that "somehow" get called. The subject is discussed at Wikipedia: http://en.wikipedia.org/wiki/Inversion_of_control


These three are all different concepts, but they all work well together, and so Spring apps often make use of all of it at once. I'll give you an example.

Let's say that we have a web application that can do many different things. We could construct this application in many ways, but one way is to create a class that is in charge of doing each of these things. We need to invoke and create these classes from somewhere. One option is to have a big main class that creates one of each of these services, opens up a socket, and passes calls to these services as they come in. Unfortunately, we've gone and created ourselves a god class, which has way too much logic and knows way too much about how everything in our program works. If we change anything about our program, we're probably going to need to modify this class.

Also, it's difficult to test. We can't test any class in isolation if it runs around instantiating and invoking the other classes directly. Unit tests become much, much harder to write.

A way to get around this is to use inversion of control. We say "okay, these are service classes. Who instatiates them? Not me." Usually, each one defines an interface, like LoginService or BillingService. There might be more than one implementation of that interface, but your app doesn't care. It just knows that it can ask for a certain kind of a service or a service with a certain name, and it'll get something nice back.

Dependency injection allows us to wire all of our litle pieces together. Classes have accessible fields, constructor arguments, or setter methods that are references to the other components that they'll need to access. That makes unit testing much easier. You can create the object under test, throw a mock or stub dependency at it, and then test that the object behaved correctly in isolation.

Now, our real application is a complex jumble of pieces that all need to be wired together just so. There are many ways to accomplish this, including allowing the application to make guesses ("this class wants a UserService, there is exactly one other class I'm in charge of that implements UserService") or by carefully explaining how they wire together in XML or Java. Spring, at its core, is a service that takes care of wiring these classes together.

Now we get to AOP. Let us say that we have all of these classes that are wired to each other in elaborate ways. There are some cross-cutting concerns that we might want to describe in very generic ways. For instance, perhaps you'd like to start a database transaction whenever any service is invoked, and commit that transaction so long as the service doesn't throw an exception. It turns out that Spring is in a unique position to perform such a task. Spring can create proxy classes on the fly that implement whatever interface your classes need, and it can wrap your class in its proxy. Now, IoC and dependency injection certainly aren't necessary to do aspect-oriented programming, but it's an extremely convenient way to accomplish it.