The Basic Concept Of IOC

Preview:

DESCRIPTION

 

Citation preview

The Basic Concept Of IOC (Implement with Spring Framework)

Kevin Lu yotsuba1022@gmail.com

Agenda • Why Spring Framework?

• Inversion of Control

• Factory Pattern

• Spring Container, Configuration and DI

• DIY

• Conclusion

Why Spring Framework? • It’s a lightweight framework:

The core of Spring is less than 1MB.

• Non-Intrusive: You can use SpringFramework without any implementation or extension. This can let you feel less the existence of Spring and significantly reduce the burden when transplant your applications.

• Inversion of Control(IOC): We know it’s important to achieve decoupling when building an application, and IOC will help you to reach this goal easily.

Inversion of Control

In this picture, it’s intuitive that all objects controlled by the dependency injector is more better than the complex relationship in traditional situation.

What’s IOC?

Inversion of Control • What’s Dependency?

When a class extend, implement another class, or maybe call some other classes, we call this class depends on another class. Ex: public class Cat implements Animal{ public String makeSound(String sound){ return sound; }

}

Inversion of Control • It’s important to reduce the dependency between each components,

when the dependency is too high, it may reduce the reusability of your applications. So, for the sake of high reusability, we should strive to reduce the dependency between each components.

Factory Pattern • In design pattern, the factory pattern can separate the code of

creating instances and let other parts which need to use the same code to reuse those separated code.

Factory Pattern • If you want to develop a logger, you may design as below at the

first time.

Factory Pattern • Build the object you need:

public class AService{ private final Logger logger = new ConsoleLogger(); //Other code… }

• If you need to use more logger, you must modify your program: public class AService{ private final Logger consoleLogger = new ConsoleLogger(); private final Logger fileLogger = new FileLogger(); //Other code… }

Factory Pattern • To solve this problem, we can use factory pattern to handle it.

Factory Pattern • Delegate the factory to achieve the job of creating objects.

public class LoggerFactory{ public static Logger createLogger(String kind){ if(“File”.equals(kind)){ return new FileLogger(); } if(“Console”.equals(kind)){ return new CinsoleLogger(); } } return null; }

Factory Pattern • So, all objects you need will be created by the factory…

public class AService{ private final Logger consoleLogger = LoggerFactory.createLogger(“Console”); }

Spring Container • The container gets its instructions on what objects to instantiate,

configure, and assemble by reading configuration metadata.

• The configuration metadata is represented in XML, Java annotations, or Java code.

Configuration Metadata • XML-based configuration metadata shows these beans configured as

<bean /> elements inside a top-level <beans /> element.

Ex: <?xml version="1.0" encoding="UTF-8"?>

<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-3.0.xsd">

<bean id="..." class="...">

<!-- collaborators and configuration for this bean go here -->

</bean>

<bean id="..." class="...">

<!-- collaborators and configuration for this bean go here -->

</bean>

<!-- more bean definitions go here -->

</beans>

Instantiating a container • The location path or paths supplied to

an ApplicationContext constructor are actually resource strings that allow the container to load configuration metadata from a variety of external resources such as the local file system, from the Java CLASSPATH.

• You can use the application context constructor to load bean definitions from all these XML fragments.

Ex: ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

Instantiating a container • Alternatively, use one or more occurrences of

the <import/> element to load bean definitions from another file or files.

Ex :

<beans>

<import resource="services.xml"/>

<import resource="resources/messageSource.xml"/>

<import resource="/resources/themeSource.xml"/>

<bean id="bean1" class="..."/>

<bean id="bean2" class="..."/>

</beans>

Naming Bean • Use the id and/or name attributes to specify the bean identifier(s).

• You can also specify them in the name attribute, separated by a comma (,), semicolon (;), or white space. As a historical note

• You are not required to supply a name or id for a bean.

Ex :

<bean class="examples.ExampleBean"/>

<bean id="exampleBean1" class="examples.ExampleBean"/>

<bean name="exampleBean2" class="examples.ExampleBean"/>

<bean name="exampleBean3,exampleBean4" class="examples.ExampleBean"/>

Using the container • Using the method getBean(String name) you can retrieve instances

of your beans

Ex: //create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

//retrieve configured instance PetStoreServiceImpl service = context.getBean("petStore");

Dependency Injection DI(Dependency Injection) exists in two major variants

• Constructor-based dependency injection

• Setter-based dependency injection

DIY • Now, it’s time to write some code, before start, you’ll need the

following things:

o STS(Spring Tool Suite)

o JAVA(SE1.6)

o Maven(Not necessary)

Build your project • In STS, build your own project. Here I build a Maven

project because I want to use pom.xml to include JUnit4.0 and spring-context, if you don’t like maven, just choose the way you like.

Build Employee • First, create an interface, here I named it “Employee”.

Build Employee • With an interface, we should implement it, so create a class

named “ProjectManager”(Maybe you like other career, it’s up to you).

Build Item • And each employee has their own computer, maybe PC or

Notebook. With this situation, we can create an interface named “Computer”.

Build Item • Let’s implement the interface “Computer”. First, we create a

class “PersonalComputer”.

Build Item • And then the class “NoteBook”.

Ready To Go • Now, we’ve create all the employee and items we need. So

it’s time to simulate the following situations:

o Before IOC.

o After IOC.

o Using Spring.

Before IOC • Before we realize the concept of IOC, we may coding as

below: You can see that there are keywords “new” here. In fact, “new” here will generate dependency between class “IdiotIT”, “PersonalComputer”, and “ProjectManager”.

Before IOC • Running “IdiotIT”, the result may like following:

Before IOC • If using UML, it may like this: It’s clearly that there are

dependencies between these classes, and it’s not a well-design program.

After IOC • So, how can I reduce, or eliminate the dependency between

these classes? Remember? We’ve told “Factory Pattern” before. So let’s build our factory to generate computers…

After IOC • Using factory to generate our computers…

After IOC • See? The result is very normal too. But we eliminate the

dependency between “IdiotIT2” and “PersonalComputer”.

After IOC • In UML, it will like this: It means that you can change the

code of “PersonalComputer” without any modification about “IdiotIT2”.Because “IdiotIT2” only depends on “ComputerFactory”

After IOC

But, there are still some problems…

After IOC • Let’s back to the “ComputerFactory” we’ve built. Here we can

know that if we need to add more type of computers, we’ll write more “if” block in this class…

After IOC • OK, just like this. This is not a well-design program because

it repeat the “if” block too many times.

.

.

.

.

.

After IOC

So, we need some mechanism that can help us to reduce those repeat blocks…

After IOC(Phase-II) • It’s time to use reflection mechanism…, here we can create a

new factory that using reflection. With reflection, our factory can be enhanced so that there will not appear any repeated “if” block.

After IOC(Phase-II) • With enhanced factory, now we can see that there are no

dependencies between IdiotIT2, ProjectManager and PersonalComputer. The only one dependency here is between IdiotIT and our factory.

After IOC(Phase-II) • Now, run our new version of IdiotIT2 to see the result.

After IOC(Phase-II) • The result looks like very normal. And here we can notice

that although we generated two personal computers, the factory still use the first one it generated.

Using Spring

The above we were talking about was what Spring done for us behind your code, now let’s take a look to see how to use Spring to reach IOC in our application.

Using Spring • Now you’ve known what’s IOC, so let’s using Spring to help us

to do all of these things. If you want to use maven, you can add the following dependencies in your pom.xml.

Using Spring • Create a configuration file, here I named it “Spring-

configuration.xml”, well, it’s up to you.

Using Spring • With this xml configuration file, we can tell Spring which

bean needs to be managed. And set some properties to the specified bean.

Using Spring • Now, create a class to test. Here you can use

“ClassPathXmlApplicationContext” to load the configuration we defined before.

Using Spring • And when we need to call the beans defined in configuration

file, we should call the ApplicationContext object first, then using “getBean” method with the bean id.

Using Spring • Hmm, it works well.

Conclusion

We’ve discussed the basic concept of IOC, and implemented it with Spring Framework, I hope that it could make you more realize about why we need to follow this mechanism and how does it work. Wish you have a more comfortable develop experience with IOC.

Thank you for your attention!