preface

Text has been included to my lot warehouse, welcome Star:https://github.com/bin392328206/six-finger plant a tree is the best time ten years ago, followed by now

omg

Yesterday there was a group of friends take 37 mutual entertainment interview, and then was asked a few questions, and then I look, I wipe, to tell the truth, they do not necessarily answer up, so here to record, and learn, the others but this year’s interview? ah

Talk about fast retransmission

In fact, this test is the knowledge of the network, if we developers, has been deeply ploughed in the business, then we may be vulnerable to this convenient

Fast retransmission mechanism

We know about Tcp timeout retransmission, so let’s think about some of the disadvantages of timeout retransmission

  • When a packet segment is lost, the packet is retransmitted after a timeout period, increasing the end-to-end delay.
  • When a packet segment is lost, in the process of waiting timeout, the following packet segment may be received by the receiving end but cannot be acknowledged. The sending end considers that the packet segment is also lost, resulting in unnecessary retransmission, which wastes resources and time.

Fortunately, TCP uses the cumulative acknowledgement mechanism. That is, when the receiving end receives a packet segment with a larger sequence number than expected, it sends the acknowledgement signal of the latest acknowledged packet segment repeatedly, which is called a duplicate ACK. As shown in the figure, packet segment 1 is successfully received and ACK 2 is confirmed. The expectation number of the receiving end is 2. When packet segment 2 is lost, packet segment 3 is out of order and does not match the expectation of the receiving end, and the receiving end repeatedly sends redundant ACK 2.

After I send this packet, the sender will continue to send the following packet, but if the receiver is not sure that it received, then it will continue to send the number of the sender that did not receive the ACK

So, if before the timeout retransmission timer overflow, receive continuous three repeat redundancy ACK (is actually received four same ACK, the first is normal, after three is redundant), the sender will know which message long lost in transit, so resend the paper passage, no need to wait for timeout retransmission timer overflow, greatly improving the efficiency. This is the fast retransmission mechanism.

Why three redundant ACKS

First of all, even if the sender sends packets in sequence, TCP packets are encapsulated in IP packets. IP packets are out of order during transmission, which means that the TCP packets arriving at the receiver are also out of order. If the packets are out of order, the receiver will send redundant ACK packets. Whether sending redundant ACKS is due to out-of-order or packet loss needs to be weighed, because using three redundant ACKS as a criterion for loss is itself an estimate.

Implement a simple IOC container yourself

Spring has so much code, half of it is IOC. How could I possibly write it? But if you think about it, IOC is not that much (I’m talking about the core idea), but it is still difficult to achieve its scalability and robustness. Let’s start today to achieve the simplest IOC

Dao has no art, art can be found

What is IOC?

IOC is an Inversion of Control, which most books translate as “Inversion of Control.”

The concept of IOC was first introduced in 1996 by Michael Mattson in an article exploring object-oriented frameworks. For the basic idea of object-oriented design and programming, we have talked a lot, in front of the needless, is simply the complex system is decomposed into mutual cooperation object, the object class by encapsulating, internal implementation external is transparent, thus reducing the complexity of problem solving, flexible and can be reused and expanded.

IOC theory puts forward something like this:Decouple dependent objects with the help of a “third party”. The diagram below:

You see, due to the introduction of the middle position of the “third party”, namely the IOC container, makes A, B, C, D the four objects without coupling, gear transmission between all rely on the “third party”, all turned over control of all objects to “third party” the IOC container, so the IOC container is the key to the core of the whole system, It acts as a kind of “glue” that binds all the objects in the system together. Without this “glue”, objects lose contact with each other, which is why some people refer to the IOC container as the “glue”.

Let’s do another experiment: remove the IOC container in the middle of the image above and look at the system again:


The picture we’re looking at right now is all we need to do to implement the whole system. At this point, objects A, B, C, AND D are no longer coupled to each other, so that when you implement A, you do not need to consider B, C, and D at all, and the dependency between objects has been reduced to the lowest degree. So what a wonderful thing it would be for system development if an IOC container could be implemented, and everyone involved could just implement their own classes, no relation to anyone else!

Why is inversion of control (IOC) so called? Let’s compare:

Before the software system introduced IOC container, as shown in Figure 1, object A depends on object B, so when object A is initialized or running to A certain point, it must take the initiative to create object B or use the already created object B. Whether you create or use object B, you have control.

After the introduction of IOC container into the software system, this situation completely changes. As shown in Figure 3, due to the addition of IOC container, object A and object B lose direct contact. Therefore, when object A runs and needs object B, IOC container will take the initiative to create an object B and inject it into the place where object A needs it.

The process by which object A acquires dependent object B is changed from active to passive, and control is reversed, hence the name “inversion of control”.

I need to find a middleman and tell him what I need and he will prepare it for me. This is the essence of IOC. The way is simple

Component design

We need a BeanFactory IOC container, then a BeanDefinition, and of course a resource loader to load the Bean

The container is used to store the initialized Bean. BeanDefinition is the basic data structure of the Bean, such as Bean name, Bean property PropertyValue, Bean method, lazy loading or not, dependency relationship, etc. The resource loader is simple, just a class that reads an XML configuration file, reads each tag and parses it.

Design of the interface

BeanFactory

First of all, we need a BeanFactory, which is a Bean container. The container interface has at least two simplest methods, one is to get the Bean and one is to register the Bean

package com.liuliu.ioc;

/ * ** @author little six six* @ version 1.0 * @date 2020/9/24 16:20 * A beanFactory is required to define the behavior of the IOC container such as fetching beans by name, such as registering beans, taking the bean name, and defining the bean* /public interface BeanFactory {  / * ** Gets the bean object from the container based on its name * * @param name Specifies the bean name * @returnThe bean instance* @throws Exception* / Object getBean(String name) throws Exception;  / * ** Register the bean into the container * * @param name Specifies the bean name* @param bean Bean instance* @throws Exception* / void registerBeanDefinition(String name, BeanDefinition bean) throws Exception; }  Copy the code

BeanDefinition

After defining the Bean’s most basic container, we also need a simple BeanDefinition interface. For convenience, but since we don’t need to consider extensions, we can design it directly as a class. What elements and methods do beanDefinitions need? You need a Bean object, a Class object, a ClassName string, and a collection of elements called PropertyValues. And that makes up a very basic BeanDefinition class. So what are the methods needed? It’s basically a get set method for these properties. Let’s look at the details of this class:

package com.liuliu.ioc;

/ * ** @author little six six* @ version 1.0 * @date 2020/9/24 16:21 * /public class BeanDefinition { / * * * bean * / private Object bean;  / * ** The CLass object of the bean* / private Class beanClass;  / * ** The class-qualified name of the bean* / private String ClassName;  / * ** A collection of attributes for the class* / private PropertyValues propertyValues = new PropertyValues();  / * ** Get the bean object* / public Object getBean() {  return this.bean;  }  / * ** Sets the object of the bean* / public void setBean(Object bean) {  this.bean = bean;  }  / * ** Get the bean's Class object* / public Class getBeanclass() {  return this.beanClass;  }  / * ** Generate Class objects by setting Class name reflection* / public void setClassname(String name) {  this.ClassName = name;  try {  this.beanClass = Class.forName(name);  } catch (ClassNotFoundException e) {  e.printStackTrace();  }  }  / * ** Gets the bean's property collection* / public PropertyValues getPropertyValues() {  return this.propertyValues;  }  / * ** Set the bean's properties* / public void setPropertyValues(PropertyValues pv) {  this.propertyValues = pv;  }  }  Copy the code

BeanDefinitionReader

Now that we have our basic BeanDefinition data structure, we also need an action class that reads from XML and parses into BeanDefinition. First we define a BeanDefinitionReader interface, which is just an identifier, Concrete by the abstract class to implement a basic method and define some basic properties, such as a registry container to store when reading, also need a delegate a ResourceLoader ResourceLoader, for loading XML files, and we need to set the constructor must contain a ResourceLoader, There are also get set methods.

  • AbstractBeanDefinitionReader
package com.liuliu.ioc;

import java.util.HashMap;
import java.util.Map;

/ * ** @author little six six* @ version 1.0 * @date 2020/9/24 16:44 * /public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader {  / * ** Register the bean container* / private Map<String, BeanDefinition> registry;  / * ** Resource loader* / private ResourceLoader resourceLoader;  / * ** The constructor must have a resource loader, and the default plug-in creates a map container * * @param resourceLoader resourceLoader* / protected AbstractBeanDefinitionReader(ResourceLoader resourceLoader) {  this.registry = new HashMap<>();  this.resourceLoader = resourceLoader;  }  / * ** Get containers* / public Map<String, BeanDefinition> getRegistry() {  return registry;  }  / * ** Get the resource loader* / public ResourceLoader getResourceLoader() {  return resourceLoader;  }  } Copy the code
  • BeanDefinitionReader Reserved interface
package com.liuliu.ioc;

/ * ** @author little six six* @ version 1.0 * @date 2020/9/24 16:44 * Reads the interface defined by the bean* /public interface BeanDefinitionReader { }  Copy the code

– XML reads the related class – Resource

package com.liuliu.ioc;

/ * ** @author little six six* @ version 1.0* @date 2020/9/24 16:46 * / import java.io.InputStream;  / * ** Resource definitions* * @author stateis0 * /public interface Resource {  / * ** Get the input stream* / InputStream getInputstream() throws Exception; }  Copy the code
package com.liuliu.ioc;

import java.net.URL;

/ * ** @author little six six* @ version 1.0 * @date 2020/9/24 16:46 * /public class ResourceLoader {  / * ** Given a location, load the URL with the accumulator's resource and create a "resource URL" object to get the input stream easily* / public ResourceUrl getResource(String location) {  URL url = this.getClass().getClassLoader().getResource(location);  return new ResourceUrl(url);  } }  Copy the code
package com.liuliu.ioc;

/ * ** @author little six six* @ version 1.0 * @date 2020/9/24 16:46 * / import java.io.InputStream; import java.net.URL; import java.net.URLConnection;  / * ** resource URL* /public class ResourceUrl implements Resource {  / * ** class library URL* / private final URL url;  / * ** A library URL is required* / public ResourceUrl(URL url) {  this.url = url;  }  / * *Get the input stream from the URL* / @Override  public InputStream getInputstream() throws Exception {  URLConnection urlConnection = url.openConnection();  urlConnection.connect();  return urlConnection.getInputStream();   }  }  Copy the code

XmlBeanDefinitionReader

Ok, AbstractBeanDefinitionReader elements required has had, however, obviously cannot implement this method reads BeanDefinition task. So we need a class to inherit an abstract class, to achieve specific methods, now that we are read the XML configuration files, then we will define a AbstractBeanDefinitionReader XmlBeanDefinitionReader inheritance, Implement some of the required methods, such as readrXML to read THE XML, such as registering parsed elements into Registry’s Map, and some of the parsing details. Let’s just look at the code.

package com.liuliu.ioc;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;  import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.InputStream;  / * ** @author little six six* @ version 1.0 * @date 2020/9/24 16:55 * Parsing XML files* /public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {  / * *Constructor, which must contain a resource loader * * @param resourceLoader resourceLoader* / public XmlBeanDefinitionReader(ResourceLoader resourceLoader) {  super(resourceLoader);  }   public void readerXML(String location) throws Exception { // Create a resource loader ResourceLoader resourceloader = new ResourceLoader(); // Get the input stream from the resource loader InputStream inputstream = resourceloader.getResource(location).getInputstream(); // Get the document Builder factory instance DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // Factory creates document builder DocumentBuilder docBuilder = factory.newDocumentBuilder(); // The document builder parse stream returns the document object Document doc = docBuilder.parse(inputstream); // Parses the given document object and registers it in the bean container registerBeanDefinitions(doc); / / close the flow inputstream.close();  }  / * ** Parses the given document object and registers it in the bean container * * @param doc document object* / private void registerBeanDefinitions(Document doc) { // Reads the root element of the document Element root = doc.getDocumentElement(); // Parse the root node of the element and all children of the root node and add them to the registry container parseBeanDefinitions(root);  }  / * ** Parse the root node of the element and all children under the root node and add them to the registry container * * @param root Root of the XML file* / private void parseBeanDefinitions(Element root) { // Reads all the children of the root element NodeList nl = root.getChildNodes(); // Iterate over the child elements for (int i = 0; i < nl.getLength(); i++) { // Gets the node at the given position of the root element Node node = nl.item(i); // Type judgment if (node instanceof Element) { // Force a parent element Element ele = (Element) node; // Parse to a given node, including name, class, property, name, value, ref processBeanDefinition(ele);  }  }  }  / * ** Resolves to a given node, including name, class, property, name, value, ref * * @param ele XML parsing element* / private void processBeanDefinition(Element ele) { // Gets the name attribute of the given element String name = ele.getAttribute("name"); // Gets the class attribute of the given element String className = ele.getAttribute("class"); // Create a bean definition object BeanDefinition beanDefinition = new BeanDefinition(); // Set the fully qualified class name of the bean definition object beanDefinition.setClassname(className); // Inject a member variable from the configuration file into the bean addPropertyValues(ele, beanDefinition); // Add the bean name and bean definition to the registry container getRegistry().put(name, beanDefinition);  }  / * ** Add attribute elements from the configuration file to the bean definition instance * * @param ele element* @param BeanDefinition bean defines the object* / private void addPropertyValues(Element ele, BeanDefinition beandefinition) { // Gets the set of property attributes for the given element NodeList propertyNode = ele.getElementsByTagName("property"); // loop set for (int i = 0; i < propertyNode.getLength(); i++) { // Gets the node at a given position in the collection Node node = propertyNode.item(i); // Type judgment if (node instanceof Element) { // Force nodes down to child elements Element propertyEle = (Element) node; // The element object gets the name attribute String name = propertyEle.getAttribute("name"); // The element object gets the value of the attribute String value = propertyEle.getAttribute("value"); // Check that value is not null if(value ! = null && value.length() > 0) {// Add the member variable to the given bean definition instance beandefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value));  } else { // If null, get the attribute ref String ref = propertyEle.getAttribute("ref");  if (ref == null || ref.length() == 0) { // If the attribute ref is empty, an exception is thrown throw new IllegalArgumentException(  "Configuration problem: <property> element for property '"  + name + "' must specify a ref or value");  } // If not empty, create an instance of "bean reference" with the construction parameter name and the instance temporarily empty BeanReference beanRef = new BeanReference(name); // Add member variables to the given "bean definition" beandefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanRef));  }  }  }  }  }  Copy the code

The code comments are very detailed, and the class methods are as follows:

  • Public void readerXML(String location) Public method of parsing XML, given a String argument of a location.
  • Private void registerBeanDefinitions(Document Doc) Gives a Document object and parses it.
  • Private void parseBeanDefinitions(Element root) Given a root Element, loop through all the children of the root Element.
  • Private void processBeanDefinition(Element ele) Gives a child Element, parses the Element, and creates a BeanDefinition object with the parsed data. And register with BeanDefinitionReader’s Map container, which holds all beans at parse time.
  • Private void addPropertyValues(Element ele, BeanDefinition BeanDefinition) The property element in the element is parsed and injected into the BeanDefinition instance. It takes five steps to parse the XML file. The ultimate goal is to put parsed files into BeanDefinitionReader’s Map.

A real Bean container

Ok, so now that we’re done reading and parsing from the XML file, when do we put it into the BeanFactory container? Just we just in the AbstractBeanDefinitionReader registered in the container. So how do we build a Bean that actually works based on the BeanFactory design? Because those beans are just information about some beans. There are no beans for our real business needs.

package com.liuliu.ioc;

import java.util.HashMap;

/ * ** @author little six six* @ version 1.0 * @date 2020/9/24 16:58 * An abstract class that implements bean methods and contains a map that stores the name of the bean and its definition* /public abstract class AbstractBeanFactory implements BeanFactory {  / * ** container* / private HashMap<String, BeanDefinition> map = new HashMap<>();  / * ** Get the bean based on its name, if not, throw an exception if so, get the bean instance from the bean definition object* / @Override  public Object getBean(String name) throws Exception {  BeanDefinition beandefinition = map.get(name);  if (beandefinition == null) {  throw new IllegalArgumentException("No bean named " + name + " is defined");  }  Object bean = beandefinition.getBean();  if (bean == null) {  bean = doCreate(beandefinition);  }  return bean;  }  / * ** Register the abstract method implementation of the bean definition, which is a template method that calls the subclass method doCreate,* / @Override  public void registerBeanDefinition(String name, BeanDefinition beandefinition) throws Exception {  Object bean = doCreate(beandefinition);  beandefinition.setBean(bean);  map.put(name, beandefinition);  }  / * ** Reduce one bean* / abstract Object doCreate(BeanDefinition beandefinition) throws Exception; } Copy the code

This class implements the two basic methods of the interface, getBean and registerBeanDefinition. We also design an abstract method for these two methods to call, deferring the concrete logic creation logic to subclasses. What is this design pattern? Template mode. The main thing is to look at the doCreate method, which is to create the bean concrete method, so we still need a subclass, what is it called? AutowireBeanFactory, which automatically injects beans, is the job of our standard Bean factory. What about the code?

As you can see, the doCreate method uses reflection to create an object, and it also needs to inject properties into the object. If the property is of type REF, then it is a dependency and needs to call getBean recursively to find the Bean (because the property of the last Bean must be of a primitive type). This completes a fetching of the instantiated Bean and also implements class dependency injection.

conclusion

With this code, we have implemented a simple IOC dependency injection function and gained a better understanding of IOC so that we will no longer be overwhelmed by Spring initialization problems. Look directly at the source code can solve. But that’s just the tip of the iceberg, you still have to implement package scanning, scan beans need to be injected into the container first, Spring has all kinds of pre-processor and post-processor, and it has level 3 cache, we only have level 1 cache, and so on.

The code is posted on Github at: a simple IOC for your own implementation, including dependency injection

Good luck!!

Daily for praise

Ok, everybody, that’s all for this article, you can see people here, they are real fans.

Creation is not easy, your support and recognition, is the biggest motivation for my creation, we will see in the next article

Six pulse excalibur | article “original” if there are any errors in this blog, please give criticisms, be obliged!