Easy understanding of control reversal and dependency injection in Spring (2), spring reversal

Source: Internet
Author: User

Easy understanding of control reversal and dependency injection in Spring (2), spring reversal

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.

The structure between classes is as follows:


The following code is used:


   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.


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 );}


  BeanInfo class: use Hash MapStore Bean information. Note that the Class path defined by Bean is stored, so that the type can be obtained and the Bean defined by reflection instantiation can be used.


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) ;}} Person: Beanpackage ioc defined in the xml file. bean;/*** Created by zzf on 2016/10/26. */public class Person {private String username; private String password; public String getUsername () {return username;} public void setUsername (String username) {this. username = username;} public String getPassword () {return password;} public void setPassword (String password) {this. password = password ;}}



 AbstractBeanFactory interface:Is the abstract base class that implements the BeanFactory interface. To obtain Bean definitions. It is the most critical class to implement logic. Registration, reading, analysis, and injection are all called by methods in this class. You can search for specific methods. YesTop-level IOCThis class is used to retrieve the registered object from the Register, and to convert the object description information to the object instance.

  Abstract method setReader: The subclass determines what kind of register reader to use. The template method is used here. The parent class defines the abstract method, but the subclass can freely design the method content, that is, the Implementation class of SourceReader is selected by the subclass.

  ParseBead method:Parse and generate object instances, mainly throughReflection complete, Load the specified Class according to the Class name, and obtain the Class object of this Class. Use the Class object to instantiate this Class and get an object. Set the values of object fields one by one. Reflection is used to call setter Method.

LoadBeans method:In the implementation class of SourceReader, the main function is to load the Bean content defined in Xml and store its attribute information in the BeanInfo class.

  ParseBean (beanInfo): Analyzes the BeanInfo stored in the loadBeans method and injects it into the Person class through reflection calls.


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. */public abstract class implements actbeanfactory implements BeanFactory {private String filePath; private Map <String, BeanInfo> container; protected SourceReader reader; public implements actbeanfactory (String filePath) {this. filePath = filePath;}/***** @ param reader */protected abstract void setReader (SourceReader reader); // register bean public void registerBeans () {this. container = this. reader. loadBeans (filePath) ;}@ Override public Object getBean (String name) {BeanInfo beanInfo = this. container. get (name); if (beanInfo = null) {return null;} else {return this. parseBean (beanInfo) ;}}/***** @ 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 );}}
SourceReader: Register the reader interface, design the abstract method of the top-level reader, and read the object registered by the user. The class inheriting this interface can implement multiple reading methods, such as reading from the configuration file, read by annotation, read from network, etc.
package ioc.reader;import ioc.info.BeanInfo;import java.util.Map;/** * Created by zzf on 2016/10/26. * */public interface SourceReader {    Map<String,BeanInfo> loadBeans(String filePath);}


XMLContext: The context of XML inherits AbstractBeanFactory. The more important method is setReader (). In the parent class, this method is an abstract method, this means that the sub-class can implement the desired reading method. This method specifies the registration reader (XML used here, the reader can implement another method such as annotation based on interest) and load the registered object at one time when constructing this method.


Package ioc. context; import ioc. factory. abstractBeanFactory; import ioc. reader. sourceReader; import ioc. reader. XMLSourceReader;/*** Created by zzf on 2016/10/26. * context constructor **/public class XMLContext extends AbstractBeanFactory {public XMLContext (String filePath) {super (filePath); this. setReader (new XMLSourceReader (); super. registerBeans () ;}@ Override protected void setReader (SourceReader reader) {super. reader = reader ;}}



  XmlContext class:Inherits the AbstractBeanFactory abstract class to register beans and register XML readers. Note that the returnedMap <String, BeanInfo>



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 ;}}


<?xml version="1.0" encoding="UTF-8"?><beans>    <bean id="person" class="ioc.bean.Person">        <property name="username">            <value>zzf</value>        </property>        <property name="password">            <value>12345678</value>        </property>    </bean></beans>
package ioc;import ioc.bean.Person;import ioc.context.XMLContext;import ioc.factory.BeanFactory;/** * Created by zzf on 2016/10/26. */public class test {    public static void main(String[] args) {        BeanFactory factory=new XMLContext("configuration/config.xml");        Person person= (Person) factory.getBean("person");        System.out.println(person.getPassword());        System.out.println(person.getUsername());    }}


After the main method is executed, the console successfully outputs the attributes defined in xml.

The overall implementation process consists of the following steps: 1. How to read the Xml file? (Check the Code) 2. What happens after reading? A container should be temporarily stored to facilitate transmission. Here, HashMap can be used to see why the BeanInfo class is used to store class information. 3. analyze the Map <String, BeanInfo> container and extract the Bean attributes. after extraction, the username and password attributes are injected into the Person class through reflection.

Based on the SpringIOC concept described in my first article, I believe that readers should be able to clearly understand the role and general implementation process of IOC.


Related Article

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.