Develop IOC containers by yourself

Source: Internet
Author: User

I wrote my resume two days ago and wrote a sentence: proficient in Spring IoC containers. How can we be proficient? Write an IOC container by yourself.


What is IOC (inversion of control )? What is di (dependency injection )? Not much explanation, Google! I hope you will clarify several concepts first. This article will not elaborate on these concepts, but will focus on how to implement them. I will describe a simple IOC container in terms of requirements, design, and code to illustrate how IOC containers help us create class instances and how to implement dependency injection, A complete IOC container instance is provided.

I. Requirement: Implement an IOC container


1. Requirement Description:



2. concepts in the figure:


(1) Service metadata: one is our compiled class file, namely, the. Class file, and the other is an XML file. You can understand spring annotations and XML bean configuration methods.

(2) Service Definition information: The information converted from metadata, that is, the object description obtained by reading the annotation or XML file in the bean.

(3) Service Provider: instance of the object. You can understand the bean instance in spring;

(4) Service Definition information storage area: the place where the service definition information is saved;

(5) cache area of the service provider instance: the place where the service provider is saved.


3. Process description:


(1) create a container: Initialize the container. The essence is to initialize the factory inside the container, then read the metadata, convert it to the service definition information, and save it to the service definition information storage area;

(2) call service provider a: Obtain the service definition information of service provider a and determine whether there is a cache. If yes, directly call a in the cache. If no, instantiate a and put it into the cache accordingly. If a is found to be dependent on B of other service providers, search for the cache. If yes, inject B in the cache into a; otherwise, instantiate B and inject it into, cache. And so on.

(3) the above two processes are core processes. On this basis, several processes are extended:

1) Get the definition information of all service providers;

2) obtain all service provider instances;

3) Obtain a service provider instance;

4) Hot Load new service providers.


Ii. Design: based on requirements and object orientation, the IOC container is outlined by integrating several design patterns.

Note: because the source code is large, it takes a lot of space, so only some core code implementation is provided. For all the code, see my csdn code. See the description at the end of the article.


1. UML, class diagram



2. Design Description


From the class diagram, we can see that the interface-oriented programming is strictly followed. The loosely coupled design ensures scalability and flexibility.

I have defined a set of specifications for implementing IOC containers. These specifications directly represent a set of interfaces and Their Relationships. Is there any feeling of J2EE. Then, I provide a default implementation for each interface, that is, a container's default implementation. Other developers can either use all of my default implementations or all of them with custom implementations, or use default implementations for some components.


3. describes the interface and default implementation, that is, the extension point.


(1) Container interface and default implementation



Core code:

Import COM. tgb. entity. beanentity; import COM. tgb. data. idatacontext;/*** @ Author: Jialin * @ Email: [email protected] * @ Date: 2014/6/22 * @ description: container core interface */public interface icontainer {// obtain the public object getbean (string name) of a service provider instance of the container. // according to the service provider name, service name, parameters to obtain the service provided by the container // The Three determine a unique service. Public object getservice (string beanname, string servicename, object... ARGs); // get all service description information of the container public idatacontext getbeandefinitioncontext (); // obtain the description information of a service provider in the container public beanentity getbeandefinition (string name ); // obtain the cache public idatacontext getbeancachecontext () for all service provider instances in the container; // Hot load the new service provider public void initcontainerservice (string resource );}

NOTE: The container adopts the appearance mode to act as the appearance layer of the factory. The container can be customized. This is the extension point 1. In addition, the factory mode and Policy mode are used to dynamically load specific factories inside the container.


(2) Factory interface and default implementation


Core code:

Import COM. tgb. entity. beanentity; import COM. tgb. data. idatacontext; import COM. tgb. handler. handlerdecorator; import Java. io. serializable;/*** @ Author: Jialin * @ Email: [email protected] * @ Date: 2014/6/22 * @ Description: an abstract service factory that defines the algorithm skeleton for processing services, it is implemented by its subclass. * /// Use the template method to define the algorithm skeleton. The specific implementation has a subclass. Public abstract class abstractbeanfactory implements ibeanfactory, serializable {// ---------- component initialization ---------- begin ----- protected idatacontext beandefinitioncontext; // The Storage Area of the service description information protected idatacontext beancachecontext; // The cache area of the service provider instance protected handlerdecorator; // converter (metadata to service description information) // set the storage area of service description information public abstract void setbeandefinitioncontext (string beandefinitioncontextname, string Resource); // set the public abstract void setbeancachecontext (string beancachecontextname) in the cache area of the service provider instance; // set the converter (metadata to service description information) public abstract void sethandler (string defaulthandler, string handlername); @ override // template method // register the service component, initialize the service description information public final void registerbeandefinition (string resource, string cachecontext, string definitioncontext, string defaulthandler, string customhandler) {This. sethandler (defaulthandler, customhandler); this. setbeancachecontext (cachecontext); this. setbeandefinitioncontext (definitioncontext, resource );} // ---------- component initialization ---------- end ----- // ---------- service provider lifecycle ----- begin -------- // obtain the service description of a service provider public abstract beanentity getbeandefinition (string name ); // check whether the instance of the service provider has the public Abstract Boolean containsbeancache (string name); // obtain the public abstract object getbeancache (string name) of the instance of the service provider from the cache ); // create the service provider public abstract object creatbean (beanentity); // register the service provider instance to the cache public abstract object regiterbeancache (string name, object OBJ ); // ---------- service provider lifecycle ----- end -------- @ override // template method // obtain the public final object getbean (string name) of the service provider instance) {// get the definition of a bean beanentity = getbeandefinition (name); // determine whether the bean has been loaded to the cache. If yes, the system returns if (containsbeancache (name )) {return getbeancache (name);} // create the bean Instance Object beanobject = This. creatbean (beanentity); // register to the cache regiterbeancache (name, beanobject); // return bean instance return beanobject ;} // obtain all service description information public abstract idatacontext getbeandefinitioncontext (); // obtain cache information of all service instances public abstract idatacontext getbeancachecontext ();}

Note: abstractbeanfactory adopts the template method. abstractbeanfactory defines two template Methods: initializing service definition information and obtaining service provider instances. The algorithm skeleton is defined. The implementation of the method that the template method depends on is handed over to the subclass for completion. Here it is handed over to defaanbeanfactory for completion. You can implement your own beanfactory. This is an extension point 2.


(3) datacontext interface and implementation



Core code:

Import Java. util. map;/*** @ Author: Jialin * @ Email: [email protected] * @ Date: 2014/6/22 * @ description: ABSTRACT Data Storage interface */public interface idatacontext {public void initdata (Map <string, Object> map); Public void set (string name, object OBJ ); public object get (string name); Public Map <string, Object> getall ();}

Note: idatacontext defines the methods that should be available in the storage region. defaultbeandefinitioncontext is the default implementation for the service provider to describe information storage. defaultbeancachecontext is the default implementation of the service provider Instance Storage. You can customize the storage area implementation. This is the extension point 3.


(4) handler interface and implementation



Core code:

Import Java. util. map;/*** @ Author: Jialin * @ Email: [email protected] * @ Date: 2014/6/23 * @ description: abstract processor decorator * // use the decorator mode. You can dynamically add features (here, the metadata processor is dynamically added) // For example, to expand annotation, you need to expand the processor by yourself, or extended XML processor, etc. Public abstract class handlerdecorator implements ihandler {protected ihandler handler; Public void sethandler (ihandler handler) {This. handler = handler ;}@ override public Map <string, Object> convert (string String) {If (handler! = NULL) {return handler. Convert (string) ;}return null ;}}

Note: The decorator mode is used here. By default, an annotation decorator defaultannotationhandler is provided to convert the annotation information in metadata into the service provider defined information. Other developers can inherit handlerdecorator to implement their own decorators. For example, they can convert XML Information into xmlhandler defined by the service provider. The factory will, in turn, implement the parser parsing metadata. This is extension 4.


(5) Annotation



Core code:

Import Java. lang. annotation. elementtype; import Java. lang. annotation. retention; import Java. lang. annotation. retentionpolicy; import Java. lang. annotation. target;/*** @ Author: Jialin * @ Email: [email protected] * @ Date: 2014/6/22 * @ Description: indicates the service provider */@ retention (retentionpolicy. runtime) @ target ({elementtype. field, elementtype. type}) Public @ interface bean {string name ();}

Note: Three annotations are provided to describe the metadata of the service provider. Handler converts the metadata to the definition information of the service provider. Other developers can extend the annotation to implement their own annotation, then customize the parsed handler, and rewrite the createbean method of factory. This is scalability 5.


(5) define the data structure and storage service definition Information



Core code:
Import Java. util. list;/*** @ Author: Jialin * @ Email: [email protected] * @ Date: 2014/6/22 * @ Description: Service Provider description information carrier. Its data structure is as follows: ** beanentity ** name type list * @ bean annotation name arraylist * serviceentity of bean type servicentity ...... ** Name value list * @ service annotation name arraylist * paramentity ...... * Name value * @ Param annotation name parameter type */public class beanentity {private string name; // service provider name private string type; // type private object Value of the service provider instance; // service provider instance private list <serviceentity> serviceentitylist; // all services provided by the service provider public beanentity () {} public beanentity (string name, string type) {This. name = Name; this. type = type;} // omit get, Set Method}

(6) util reflection


Note: This is a Java reflection tool class that encapsulates some common reflection methods.


(7) Hot load listener


Note: This listener listens to a certain location. If new service provider metadata is added, it will be hot loaded by the container.


III. All code


1. the requirements, design, and core code are introduced above. If you are still not satisfied, let's take a look at all the code.

I have open-source this small project and managed it to the csdn code public project. Project homepage:

Https://code.csdn.net/shan9liang/ioccontainer


2. You can help with the improvement or download and view. There are still many improvements. We have been busy recently and will continue to update them when we are free of charge. Thank you for your valuable comments.





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.