Wechat public number: Orange Pine Java technology nest article first gold platform, the subsequent synchronous update of the public number, after attention to reply to “plus group” can join the Internet technology exchange & push group, and a group of big factory leaders to discuss interview questions. Reply to “666” to get all the information packages available on the First line Internet (including development software, development specifications, classic e-PDF, and some quality learning courses).

preface

Spring IOC is a core component of the Spring framework, inversion of Control (IOC). For those who are new to Spring, the design concept of IOC may be very superficial. The key to understanding IOC is to understand who controls whom and what. Why is it a reversal? What has been reversed?

Who controls who and what? Remember when you were learning servlets and creating objects inside each layer with the new keyword, remember that this is the program actively creating dependent objects; And when you get to Spring IoC has a container for creating these objects, controlling objects.

Why is it a reversal? The simple understanding is that when we actively control to get dependent objects, this is a positive transformation, right? In inversion, the container helps create and inject dependent objects. Why reverse? Because the container helps us find and inject the dependent object, the object only passively accepts the dependent object, so it is inversion; What has been reversed? The retrieval of dependent objects has been reversed.

Hand-tear the simplest IOC container

Maybe you don’t get it, think it’s abstract? Follow the bloggers hand in hand to achieve IOC!

The implementation here is just a handwritten understanding of ioc conceptsdemo.iocThere are a lot of details waiting for us to learn. If you are interested, you can go to the official account to read an article about it published beforespring iocSource read the article

Ioc is not a container. Ok, let’s define a container first. The characteristics of a container must have objects to store and fetch

Spring objects are beans, but we do not know what the bean type is, so the generic representation, and when the bean is stored in the container. Spring does an initial scan at startup, so we define an initAutoWired method to emulate that.

Start by defining a tangerine container interfaceJsContainer.
Description: Need source file plus QQ group [572411121] free request */
public interface JsContainer {

    /** * get Bean * from Class@param clazz
     * @return* /
    <T> T getBean(Class<T> clazz);

    /** * Register a Class to the container **@param clazz
     */
    Object registerBean(Class
        clazz);

    /** ** */
    void initAutoWired(a);
Copy the code
Let’s write another custom annotation identifierJsAutowiredTo get the instantiation later by reflectionbeanCustom annotations can specify the type to be injected, as well as the injectedbeanThe name.
package com.orangesongjava.ioc;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

Description: Need source file plus QQ group [572411121] free request */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JsAutowired {

    / * * *@returnThe class type to inject */Class<? > value()default Class.class;

    / * * *@returnThe bean name */
    String name(a) default "";
}
Copy the code
Now that we have the container interface and annotations, let’s think about implementing it! Let’s define a classJsSampleContainerTo implement the container interfaceJsContainer
package com.orangesongjava.ioc;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

Description: Need source file plus QQ group [572411121] free request */
@SuppressWarnings("unchecked")
public class JsSampleContainer implements JsContainer {
	/** * Save all bean objects in the format of com.xxx.xxx.xxxclass: @56x2ya */
    private Map<String, Object> beanNameMap;
    
    /** * Store the relationship between bean and name */
    private Map<String, String> beanKeys;
    
    public JsSampleContainer(a) {
    	this.beanNameMap = new ConcurrentHashMap<>();
    	this.beanKeys = new ConcurrentHashMap<>();
    }
	
	@Override
	public <T> T getBean(Class<T> clazz) {
		String name = clazz.getName();
		Object object = beanNameMap.get(name);
		if(null! = object){return (T) object;
		}
		return null;
	}

	@Override
	public Object registerBean(Class
        clazz) {
		String name = clazz.getName();
		beanKeys.put(name, name);
		Object bean = newInstance(clazz);
        beanNameMap.put(name, bean);
		return bean;
	}

	@Override
	public void initAutoWired(a) {
        beanNameMap.forEach((k,v) -> injection(v));
	}
	/** * Inject object *@param object
	 */
	public void injection(Object object) {
		// All fields
	    try {
			Field[] fields = object.getClass().getDeclaredFields();
			for (Field field : fields) {
				// The fields to be injected
                JsAutowired jsAutowired = field.getAnnotation(JsAutowired.class);
			    if (null! = jsAutowired) {// The field to be injected
			        Object autoAutoWiredField = null;
			        String name = jsAutowired.name();
			        // If the JsAutowired custom annotation does not specify the name attribute, the default value is "".
	        		if(! name.equals("")) {// Specify a specific name
	        			String className = beanKeys.get(name);
	        			if(null! = className && ! className.equals("")){
                                            autoAutoWiredField = beanNameMap.get(className);
	        			}
	        			if (null == autoAutoWiredField) {
				            throw new RuntimeException("Unable to load "+ name); }}else {
                                        // JsAutowired annotations have no name attribute
                                        // Check whether the injected type is a Class
	        			if(jsAutowired.value() == Class.class){
                                               autoAutoWiredField = register(field.getType());
				        } else {
				            // Specify the class to assemble
                                            autoAutoWiredField = this.getBean(jsAutowired.value());
				            if (null== autoAutoWiredField) { autoAutoWiredField = register(jsAutowired.value()); }}}if (null == autoAutoWiredField) {
			            throw new RuntimeException("Unable to load " + field.getType().getCanonicalName());
			        }
			        boolean accessible = field.isAccessible();
			        field.setAccessible(true); field.set(object, autoAutoWiredField); field.setAccessible(accessible); }}}catch (SecurityException e) {
        	e.printStackTrace();
        } catch (IllegalArgumentException e) {
        	e.printStackTrace();
        } catch(IllegalAccessException e) { e.printStackTrace(); }}private Object register(Class
        clazz){
        if(null! = clazz){return this.registerBean(clazz);
        }
        return null;
    }

    /** * Create an instance object *@paramClazz class object *@return* /
    public static Object newInstance(Class
        clazz) {
        try {
            return clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null; }}Copy the code

Test the

Let’s test it now. Let’s define a class OrangeSongJavaService so that the test can be called later. Note that there are no annotations on this class. That is, it is not managed by Spring.

Description: Need source file plus QQ group [572411121] free request */
package com.orangesongjava.ioc;

public class OrangeSongJavaService {
    public void writeArticleOnJs(String name){
        System.out.println(name + "Writing on the Nuggets!"); }}Copy the code

A mock call to OrangeSongJavaClient in the definition of a local call. Note that this class also has no annotations on it, and the OrangeSongJavaService reference is identified by our custom JsAutowired annotation.

Description: Need source file plus QQ group [572411121] free request */
package com.orangesongjava.ioc;

public class OrangeSongJavaClient {

    @JsAutowired
    private OrangeSongJavaService orangeSongJavaService;

    public void work(a) {
        orangeSongJavaService.writeArticleOnJs("Orange pine Java");
    }
    public OrangeSongJavaService getOrangeSongJavaService(a) {
        returnorangeSongJavaService; }}Copy the code

Now let’s write a test main method to test it.

Description: Need source file plus QQ group [572411121] free request */
package com.orangesongjava.ioc;

public class IocTest {

    private static JsSampleContainer jsContainer = new JsSampleContainer();

    public static void main(String[] args) {
        // Inject the class into the container
        jsContainer.registerBean(OrangeSongJavaClient.class);
        // Initialize injection - scan references
        jsContainer.initAutoWired();
        // The container gets the bean
        OrangeSongJavaClient client jsContainer.getBean(OrangeSongJavaClient.class);
        / / executionclient.work(); }}Copy the code

If the output execution logic, it indicates that the program is ok. Sure enough, no problem. See here, is your understanding of IOC a little clear? If you have any questions or do not understand, please leave a comment below. Bloggers give you answers.

Well, I’ll see you next time.

The last

  • The article is original, original is not easy, thanks for digging gold platform, feel harvest, help three lianha, thank you
  • Wechat search public number: Orange pine Java technology nest, make a friend, into the Internet technology exchange group
  • All code, sequence diagrams and architecture diagrams involved in the article are shared and can be requested free of charge through the public account plus group
  • If the article has the error, welcome the comment message points out, also welcome to reprint, trouble to mark the source is good