IoC container summary and simple Simulation

Source: Internet
Author: User

IoC container summary and simple Simulation

When a component requires external resources, the most direct and wise way is to perform a search. This behavior is called active search. However, this kind of search has a disadvantage: components need to know how to obtain resources. A good solution for obtaining resources is to apply IoC (Inversion of Control, Control reversal ). Its idea is to reverse the direction of resource acquisition. The traditional resource search method requires the component to initiate a request to the container to find the resource. In response, the container returns the resource in a timely manner. After IoC is applied, the container actively pushes resources to the components managed by the container. All the component has to do is select a suitable method to accept resources.

IoC is a general design principle, while DI (Dependency Injection, Dependency Injection) is a specific design model, which reflects the IoC design principles. DI is a typical Implementation of IoC, so IoC and DI terms will be mixed. The relationship between IoC and DI is the same as that between "interface" and "interface implementation class" in Java.

In DI mode, containers are solely responsible for assembly of components. Containers inject matched resources into each component in a predefined manner (such as the setter method or constructor. There are currently three types of DI:

  • Setter Injection, Setter injection may have some problems. 1. It is easy to forget to call the setter method to inject the dependencies required by the component, which will cause NullPointerException. 2. The Code may have security issues. After the first injection, you cannot stop calling setter again unless you add additional processing work. However, because setter injection is very simple, it is very popular (most Java IDE supports automatic setter generation ).
  • Constructor InjectionConstructor injection can solve the problem of setter injection to a certain extent. However, the injection method also brings about some problems. If the component has many dependencies, the parameter list of the constructor will become lengthy, reducing the code readability.
  • Interface InjectionThe injection method is rarely used. It requires that the component must implement an interface through which the container injects dependencies. Interface injection has obvious disadvantages. Interface injection requires specific interfaces, and interfaces are specific to containers. Therefore, components depend on containers. Once they are separated from containers, components cannot be reused. This is an "intrusive" injection.

Among them, "setter injection" and "constructor injection" are widely used, and most IoC containers support these two DI types.

 

Imitating Spring IoC containers

Assume that one of the functions of a system is to generate reports in PDF or HTML format.

/* Common Report Generation interface */
Public interface ReportBuilder
{
Public void build (String data );
}

Implementation classes for generating PDF and HTML formats:

/* Generate an HTML report */
Public class ReportHtmlBuilder implements ReportBuilder {
@ Override
Public void build (String data ){
/* Sample Code */
System. out. println ("build html report! ");
}
}

/* Generate a report in PDF format */
Public class ReportPdfBuilder implements ReportBuilder {
@ Override
Public void build (String data ){
System. out. println ("build pdf report! ");
}
}

Report service class:

/* Report service class */
Public class ReportService
{
/* Dependency "ReportBuilder "*/
Private ReportBuilder builder;

Public ReportBuilder getBuilder ()
{
Return builder;
}

/* Setter injection */
Public void setBuilder (ReportBuilder builder)
{
This. builder = builder;
}

Public void builderYearReport (int year)
{
This. builder. build ("data ");
}
}

IoC container configuration file "component. properties"

pdfBuilder=com.beliefbitrayal.ioc.inter.imp.ReportPdfBuilder
htmlBuilder=com.beliefbitrayal.ioc.inter.imp.ReportHtmlBuilder
reportService=com.beliefbitrayal.ioc.server.ReportService
reportService.builder=htmlBuilder

IoC container:

Public class Container
{
/* Container used to store Component */
Private Map <String, Object> repository = new HashMap <String, Object> ();

Public Container ()
{
Try
{
/* Read the container configuration file "component. properties "*/
Properties properties = new Properties ();
Properties. load (new FileInputStream ("src/component. properties "));

/* Get the information of each line in the configuration file */
For (Map. Entry <Object, Object> entry: properties. entrySet ())
{
String key = (String) entry. getKey ();
String value = (String) entry. getValue ();

/* Process each row of the configuration file */
This. handler (key, value );
}
}
Catch (Exception e)
{
E. printStackTrace ();
}
}

Private void handler (String key, String value) throws Exception
{
/*
* ReportService = com. beliefbitrayal. ioc. server. ReportService
* ReportService. builder = htmlBuilder
* In the first case, there is no "." In the middle of the key value, which indicates a new component. Process it as the object to create it, and put its object in Map.
* In the second case, "." appears in the middle of the key value, indicating that this attribute entry is a dependency injection. The key value is divided into two parts based on the location of ".". The first part is the component name, and the second part is the component name.
* Attributes to be set for this component.
*/
String [] parts = key. split ("\\.");

/* Case 1 */
If (parts. length = 1)
{
/* Create a component object through reflection */
Object object = Class. forName (value). newInstance ();

This. repository. put (key, object );
}
Else
{
/* For Case 2, first obtain the component using the first part of the key value (component name */
Object object = this. repository. get (parts [0]);

/* Use the component name specified by the value to obtain the dependency from the Map object */
Object reference = this. repository. get (value );

/* Inject the obtained dependency to the corresponding attributes of the specified component. The "PropertyUtils" class belongs to the Commons BeanUtil third-party class library under Apache,
* To use it, you also need to download the Commons Logging third-party class library.
*/
PropertyUtils. setProperty (object, parts [1], reference );
}
}

Public Object getComponent (String key)
{
Return this. repository. get (key );
}
}

According to the configuration file, the reports we use in the scenario class should be in HTML format:

Public class Client
{
Public static void main (String [] args)
{
/* Create a container */
Container container = new Container ();

/* Obtain the "Report service class" from the container "*/
ReportService reportService = (ReportService) container. getComponent ("reportService ");

/* Display report */
ReportService. builderYearReport (0 );
}
}

Console output:

build html report!

To modify the attribute file in PDF format, you only need:

pdfBuilder=com.beliefbitrayal.ioc.inter.imp.ReportPdfBuilder
htmlBuilder=com.beliefbitrayal.ioc.inter.imp.ReportHtmlBuilder
reportService=com.beliefbitrayal.ioc.server.ReportService
reportService.builder=pdfBuilder

The scenario class remains unchanged. Console output:

build pdf report!

Containers can read Component definitions from text-based control files, which allows containers to be reused. Now, even if you change the definition of a component at will, you do not need to modify the container code. This example demonstrates the core principles and mechanisms of the IoC container.
Through the above analysis and examples, IoC is a component dependency that is assembled by containers. The component does not perform positioning queries, but only provides a common Java method for containers to assemble dependencies, ioC containers inject dependencies to components by using setter injection or constructor injection. The dependencies of components are described by a configuration file (XML or Properties ), the Configuration File Reads and parses when the IoC container is built.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.