Simple simulation of SpringIOC working mechanism process development, springioc Mechanism
Next, I explained the basic concepts of SpringIOC and DI in the previous article "easily understand control inversion and dependency injection in Spring". In this article, we will simulate the working mechanism of SpringIOC, this gives us a deeper understanding of the work. Before proceeding to the Code, let's take a look at the design purposes of several classes.
BeanFactor Interface: The definition in Spring source code is: Hold the definition of a certain number of beans, and each Bean is uniquely identified by the object (class), you need to implement this interface. According to the Bean definition, the factory will return an independent instance (prototype design mode) containing the Bean-defined objects, or Singleton sharing (a good Singleton design mode ,) the range is the scope of the entire factory (or it can be understood as the entire container), and the type of instances returned depends on the Bean Factory configuration: the API is the same. Because Spring2.0 expands the scope of dependencies, BeanFactory is the central registration center and centralized configuration of application components based on the application's upstream and downstream questions (such as requests and sessions in the Web environment. Simply put, this interface defines the method for obtaining beans, which is implemented by sub-classes.
BeanFactory interface:Is the abstract base class that implements the BeanFactory interface. To obtain Bean definitions.
XmlContext class:Inherits the AbstractBeanFactory abstract class to register beans and register XML readers.
BeanInfo class:Store Bean information.
Next, I added the Code where the comments are needed. The directory of the class is as follows.
The structure between classes is as follows:
The following code is used:
Package ioc. factory;/*** Created by zzf on 2016/10/26. */public interface BeanFactory {/*** obtain the Object instance * @ param name * @ return */Object getBean (String name) according to the Object ID );}
Package ioc. factory; import ioc.info. beanInfo; import ioc. reader. sourceReader; import java. lang. reflect. invocationTargetException; import java. lang. reflect. method; import java. util. map;/*** Created by zzf on 2016/10/26. ** top-level IOC implementation * this class is responsible for retrieving registered objects from the register * the process of converting the object description information to the object instance * The method for obtaining objects by name **/public abstract class AbstractBeanFactory implements BeanFactory {private String filePath; private Map <String, BeanInfo> container; protected SourceReader reader; public AbstractBeanFactory (String filePath) {this. filePath = filePath; setReader (reader);}/*** determines by the subclass what kind of register reader is used. * The template method is used here. The parent class defines the abstract method, however, the sub-classes are free to design the method content * @ param reader */protected abstract void setReader (SourceReader reader); // register bean public void registerBeans () {this. container = this. reader. loadBeans (filePath) ;}@ Override public Object getBean (St Ring name) {BeanInfo beanInfo = this. container. get (name); if (beanInfo = null) {return null;} else {return this. parseBean (beanInfo) ;}}/*** parse and generate object instance * mainly through reflection complete * load specified class according to class name, and get the Class Object * use the Class object to instantiate the Class and get an object. * Set the values of Object fields one by one. Here, the setter Method is used ** @ param beanInfo specifies the description of the Object * @ return */protected Object parseBean (BeanInfo beanInfo) {Class clazz; try {// load Bean instance clazz = Class. forName (beanInfo. getType (); Object bean = clazz. newInstance (); // obtain all methods of the object, including private Method [] methods = clazz. getDeclaredMethods (); for (String property: beanInfo. getProperties (). keySet () {String setter = "set" + firstCharToUp (property); for (Method method: methods) {String methodName = method. getName (); if (methodName. equals (setter) {Object value = beanInfo. getProperties (). get (property); // call the set method Using Reflection. invoke (bean, value) ;}} return bean;} catch (ClassNotFoundException e) {e. printStackTrace ();} catch (InstantiationException e) {e. printStackTrace ();} catch (IllegalAccessException e) {e. printStackTrace ();} catch (InvocationTargetException e) {e. printStackTrace ();} return null;} private String firstCharToUp (String property) {System. out. println (property); char [] c = property. toCharArray (); String first = String. valueOf (c [0]). toUpperCase (); c [0] = first. charAt (0); System. out. println (String. valueOf (c); return String. valueOf (c) ;}} package ioc. context; import ioc. factory. abstractBeanFactory; import ioc. reader. sourceReader; import ioc. reader. XMLSourceReader;/*** Created by zzf on 2016/10/26. * context constructor * indicates the reader to be registered. (XML is used here. You can implement another method, such as annotation, based on your interests) * The registered object */public class XMLContext extends actbeanfactory {public XMLContext (String filePath) {super (filePath); this. setReader (new XMLSourceReader (); super. registerBeans () ;}@ Override protected void setReader (SourceReader reader) {super. reader = reader ;}}
Package ioc. reader; import ioc.info. beanInfo; import java. util. map;/*** Created by zzf on 2016/10/26. * register the reader interface * reads user-registered objects * The classes inherited from this interface can be read in multiple ways, such as reading from the configuration file and reading according to tags, read from the network and so on */public interface SourceReader {Map <String, BeanInfo> loadBeans (String filePath );}
Package ioc. context; import ioc. factory. abstractBeanFactory; import ioc. reader. sourceReader; import ioc. reader. XMLSourceReader;/*** Created by zzf on 2016/10/26. * context constructor * indicates the reader to be registered. (XML is used here. You can implement another method, such as annotation, based on your interests) * The registered object */public class XMLContext extends actbeanfactory {public XMLContext (String filePath) {super (filePath); this. setReader (new XMLSourceReader (); super. registerBeans () ;}@ Override protected void setReader (SourceReader reader) {super. reader = reader ;}} package ioc.info; import java. lang. object; import java. util. hashMap; import java. util. map;/*** Created by zzf on 2016/10/26. */public class BeanInfo {private String id; private String type; private Map <String, Object> properties = new HashMap <String, Object> (); public String getId () {return id;} public void setId (String id) {this. id = id;} public String getType () {return type;} public void setType (String type) {this. type = type;} public Map <String, Object> getProperties () {return properties;} public void setProperties (Map <String, Object> properties) {this. properties = properties;} public void addProperty (String name, Object object) {this. properties. put (name, object) ;}} package ioc. reader; import ioc.info. beanInfo; import org. dom4j. attribute; import org. dom4j. document; import org. dom4j. extends entexception; import org. dom4j. element; import org. dom4j. io. SAXReader; import java. beans. introspectionException; import java. beans. introspector; import java. beans. propertyDescriptor; import java. io. inputStream; import java. io. reader; import java. lang. reflect. invocationTargetException; import java. lang. reflect. method; import java. util. hashMap; import java. util. iterator; import java. util. map;/*** Created by zzf on 2016/10/26. * use dom4j to read Xml */public class XMLSourceReader implements SourceReader {@ Override public Map <String, BeanInfo> loadBeans (String filePath) {// read the specified configuration file SAXReader reader = new SAXReader (); ClassLoader classLoader = Thread. currentThread (). getContextClassLoader (); // obtain the specified xml file InputStream ins = classLoader from the class directory. getResourceAsStream (filePath); Document doc = null; try {doc = reader. read (ins);} catch (incluentexception e) {e. printStackTrace ();} // obtain the root node Element root = doc. getRootElement (); Map <String, BeanInfo> beanInfoMap = new HashMap <String, BeanInfo> (); // traverse bean for (Iterator I = root. elementIterator ("bean"); I. hasNext ();) {Element element = (Element) I. next (); // obtain the bean property id and class Attribute id = element. attribute ("id"); Attribute cls = element. attribute ("class"); try {// obtain the class Object Class bean = Class by using the Java reflection mechanism. forName (cls. getText (); // get the information of the corresponding class java. beans. beanInfo info = Introspector. getBeanInfo (bean); // get its property description PropertyDescriptor [] propertyDescriptors = info. getPropertyDescriptors (); Method method; Object object = bean. newInstance (); BeanInfo beanInfo = new BeanInfo (); for (Iterator iterator = element. elementIterator ("property"); iterator. hasNext ();) {Element foo2 = (Element) iterator. next (); // obtain the name Attribute of the property. Attribute name = foo2.attribute ("name"); String value = null; // obtain the value of the sub-Element value of the property for (Iterator ite1 = foo2.elementIterator ("value"); ite1.hasNext ();) {Element node = (Element) ite1.next (); value = node. getText (); break;} System. out. println ("name:" + name. getText () + "value" + value); for (int j = 0; j <propertyDescriptors. length; j ++) {if (propertyDescriptors [j]. getName (). equalsIgnoreCase (name. getText () {method = propertyDescriptors [j]. getWriteMethod (); // use Java reflection to call a set method of the object and set the value to method. invoke (object, value); // stores the obtained object Property Information in our custom BeanInfo. beanInfo. addProperty (name. getText (), value) ;}} beanInfo. setId (id. getText (); beanInfo. setType (cls. getText (); beanInfoMap. put (id. getText (), beanInfo);} return beanInfoMap;} catch (ClassNotFoundException e) {e. printStackTrace ();} catch (IntrospectionException e) {e. printStackTrace ();} catch (InstantiationException e) {e. printStackTrace ();} catch (IllegalAccessException e) {e. printStackTrace ();} catch (InvocationTargetException e) {e. printStackTrace () ;}} return null ;}}