• 自己模拟实现spring ioc原理


    JSON配置文件的数据结构:

    package light.zhang.ioc.bean;
    
    import java.io.Serializable;
    import java.util.List;
    
    import lombok.Data;
    import lombok.ToString;
    
    /**
     * 数据结构
     * @author witts 
     */
    @Data
    @ToString
    public class Beandefinition implements Serializable{ 
        /**
         * 序列ID
         */
        private static final long serialVersionUID = -1723354830429118453L;
        
        /**BeanName参数**/
        private String beanName;
        
        private String className;
        
        private String interfaceName;
        
        private List<ConstructorArg> ConstructorArgs;
        
        private List<PropertyArg> PropertyArgs;
    }

    参数注入类:

    package light.zhang.ioc.bean;
    
    import java.io.Serializable;
    
    import lombok.Data;
    
    @Data
    public class ConstructorArg implements Serializable {
     
        private static final long serialVersionUID = -1094744504486782050L;
        
        private String ref;
    }
    package light.zhang.ioc.bean;
    
    import java.io.Serializable;
    
    public class PropertyArg implements Serializable {
     
        private static final long serialVersionUID = 4398781604716858284L;
    
    }

    读取json配置文件:

    package light.zhang.ioc.client;
    
    import java.io.InputStream;
    import java.util.List;
    
    import com.fasterxml.jackson.core.type.TypeReference;
    
    import light.zhang.ioc.bean.Beandefinition;
    import light.zhang.ioc.core.ApplicationContextFactory;
    import light.zhang.ioc.utils.JsonUtils; 
    
    /**
     * 通过json格式的方式来存储注册信息,然后让IOC容器管理对象
     * @author witts 
     */
    public class JsonApplicationContext extends  ApplicationContextFactory {  
        private String fileName; 
        
        public JsonApplicationContext(String fileName) {
            this.fileName = fileName; 
            initFile();
        }   
        
        private void initFile(){//读取文件,并注册到容器
            InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);//读取配置文件信息
            List<Beandefinition> beanDefinitions = JsonUtils.readValue(is,new TypeReference<List<Beandefinition>>(){});  
            if(beanDefinitions != null && !beanDefinitions.isEmpty()) {
                for (Beandefinition beanDefinition : beanDefinitions) { 
                    registerBean(beanDefinition.getBeanName(), beanDefinition);//注册
                }
            }
        } 
    }

     通过名称得到bean:

    package light.zhang.ioc.core;
    
    import light.zhang.ioc.exception.CreateBeanException;
    import light.zhang.ioc.exception.LoadBeanException;
    
    public interface ApplicationContext {
        /**
         * 通过bean获取到注册的实例信息
         * @param name
         * @throws Exception
         * @throws LoadBeanException 
         * @throws CreateBeanException 
         */
        public Object getBean(String name) throws IllegalAccessException; 
        
    }

    负责bean生命周期管理,加载-实例-注册-销毁等

    package light.zhang.ioc.core;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    
    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import light.zhang.ioc.bean.Beandefinition;
    import light.zhang.ioc.bean.ConstructorArg;
    import light.zhang.ioc.exception.CreateBeanException;
    import light.zhang.ioc.exception.LoadBeanException;
    import light.zhang.ioc.utils.BeanUtils;
    import light.zhang.ioc.utils.ClassLoaderUtils;
    import light.zhang.ioc.utils.ReflectionUtils;
    
    /**
     * 主要负责对加载到Map里面的对象取舍 beanDefineMap 存储的是对象的名称和对象对应的数据结构的映射。bean 用于保存
     * beanName和实例化之后的对象。 容器初始化的时候,会调用 BeanRegisterFactoryImpl.registerBean 方法。把
     * 对象的 Beandefinition 数据结构,存储起来 当我们调用 getBean() 的方法的时候。会先到 beanMap
     * 里面查找,有没有实例化好的对象。如果没有, 就会去beanDefineMap查找这个对象对应的
     * BeanDefination。再利用DeanDefination去实例化一个对象。 对象实例化成功以后,我们还需要注入相应的参数,调用
     * populatebean()这个方法。在 populateBean 这个方法中, 会扫描对象里面的Field,如果对象中的 Field
     * 是我们IoC容器管理的对象,那就会调用 我们上文实现的 ReflectionUtils.injectField来注入对象。
     * 一切准备妥当之后,我们对象就完成了整个 IoC 流程。最后这个对象放入 beanMap 中,方便下一次使用。 所以我们可以知道 BeanFactory 是管理和生成对象的地方。
     */
    public class ApplicationContextFactory  implements ApplicationContext {
            
        private static final Logger logger=LoggerFactory.getLogger(ApplicationContextFactory.class);
    
        private static final ConcurrentHashMap<String, Object> beanMap = new ConcurrentHashMap<String, Object>();
    
        private static final ConcurrentHashMap<String, Beandefinition> undefineMap = new ConcurrentHashMap<String, Beandefinition>();
    
        private static final Set<Object> beanNameSet = Collections.synchronizedSet(new HashSet<Object>());// 同步的hash set
    
        @Override
        public Object getBean(String name) throws IllegalAccessException {
            Object bean = null;
            bean = beanMap.get(name);// 在已经注册过的情况下通过名称获取注册的实例
            if (null != bean) {
                return bean;
            }
            bean = createBean(undefineMap.get(name)); // 如果没有实例化,那就需要调用createBean来创建对象,第一次加载的情况
            if (bean != null) {
                // 对象创建成功以后,注入对象需要的参数 
                    populatebean(bean);
                    // 再把对象存入Map中方便下次使用。
                    beanMap.put(name, bean); 
            }
            // 结束返回
            logger.debug("This "+name+" is managed by ioc!!!");
            return bean;
        }
    
        /**
         * 注册bean到IOC容器里面
         * 
         * @param name
         * @param bean
         */
        protected void registerBean(String name, Beandefinition bean) {
            undefineMap.put(name, bean);// 先注册
            beanNameSet.add(name);// 添加注册信息
        }
    
        /**
         * 主要负责对参数的初始化
         * 
         * @param bean
         * @throws IllegalAccessException 
         * @throws Exception
         * @throws LoadBeanException 
         * @throws CreateBeanException  
         */
        private void populatebean(Object bean) throws IllegalAccessException   {
            Field[] fields = bean.getClass().getSuperclass().getDeclaredFields();// 获取的代理对象信息
            if (fields != null && fields.length > 0) {// 存在代理对象
                for (Field field : fields) {
                    String beanName = field.getName();
                    beanName = StringUtils.uncapitalize(beanName);// beanName字符串的第一个字符,转换为小写
                    if (beanNameSet.contains(field.getName())) {// 当包从IOC容器检测到注册信息之后
                        Object fieldBean = getBean(beanName);// 获取实例
                        if (fieldBean != null) {
                            ReflectionUtils.initParamter(field, bean, fieldBean);// 初始化参数信息
                        }
                    }
                }
            }
        }
    
        /**
         * 创建bean实例
         * 
         * @param beanDefinition
         * @return
         * @throws IllegalAccessException 
         * @throws LoadBeanException 
         * @throws Exception
         */
        private Object createBean(Beandefinition beanDefinition) throws IllegalAccessException  {
            if(null == beanDefinition) {
                try {
                    throw new CreateBeanException();
                } catch (CreateBeanException e) { 
                    e.printStackTrace();
                }
            }
            String beanName = beanDefinition.getClassName();
            Class<?> classInfo = ClassLoaderUtils.loaderClass(beanName);
            if (classInfo == null) {
                try {
                    throw new LoadBeanException();
                } catch (LoadBeanException e) { 
                    e.printStackTrace();
                }
            }
            List<ConstructorArg> constructorArgs = beanDefinition.getConstructorArgs();// 获取参数列表
            if (constructorArgs != null && !constructorArgs.isEmpty()) {
                List<Object> objects = new ArrayList<Object>();
                for (ConstructorArg constructorArg : constructorArgs) {
                    objects.add(getBean(constructorArg.getRef()));// ref引用信息
                }
                try {
                    return BeanUtils.instanceCreate(classInfo, classInfo.getConstructor(), objects.toArray());// 有参数的注入
                } catch (NoSuchMethodException e) { 
                    e.printStackTrace();
                } catch (SecurityException e) { 
                    e.printStackTrace();
                }
            } else {
                return BeanUtils.instanceCreate(classInfo, null, null);// 没有参数
            }
            return null;
        } 
    
    }

    创建对象时异常

    package light.zhang.ioc.exception;
     
    /**
     * 创建时异常
     * @author witts
     *
     */
    public class CreateBeanException extends Throwable { 
        
        private static final long serialVersionUID = 1L;
        
        public CreateBeanException() { 
            super("create bean fail,bean name is not found!!!");
        }
         /**
          * 创建bean异常
          * @param exc
          */
        public CreateBeanException(String exc) { 
            super(exc);
        }
    }

    加载bean异常

    package light.zhang.ioc.exception;
    
    /**
     * 加载时异常
     * @author witts 
     */
    public class LoadBeanException extends Throwable{ 
        
        private static final long serialVersionUID = 8520827571307312752L;
        
        @Override
        public synchronized Throwable fillInStackTrace() { 
            return super.fillInStackTrace();
        }
        
        public LoadBeanException() {
            super("load bean exception,bean not found!!!");
        }
        
        public LoadBeanException(String message) {
            super(message);
        }
    }

    bean工具类:

    package light.zhang.ioc.utils;
    
    import java.lang.reflect.Constructor;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.NoOp;
    
    /**
     * 主要负责处理对BEAN的管理,BEAN的初创建,始化,状态管理
     * @author witts 
     */
    public class BeanUtils {
        /**
         * 动态代理,并创建类
         * @param clas
         * @param constructor
         * @param args
         * @return
         */
        public static Object instanceCreate(Class<?> clas,Constructor<?> constructor,Object[] args) {
            /**
             * Enhancer允许为非接口类型创建一个Java代理。Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是类他都能正常工作
             */
            Enhancer enhancer=new Enhancer(); 
            enhancer.setSuperclass(clas);//代理类
            enhancer.setCallback(NoOp.INSTANCE);//代理类型>初始化实例
            if(null == constructor) {
                return enhancer.create();//默认创建无参数实例
            }else {
                return enhancer.create(constructor.getParameterTypes(),args);//带参数的初始化
            } 
        }
    }

    类装载工具类:

    package light.zhang.ioc.utils;
    
     /**
      * 主要负责读取配置文件,装载类信息
      * @author witts
      *
      */
    public class ClassLoaderUtils {
        /**创建读取配置信息的对象**/
        public static ClassLoader install() {
            return Thread.currentThread().getContextClassLoader();
        }
        /**装载class**/
        public static Class<?> loaderClass(String className) {
            try {
                return install().loadClass(className);//通过配置文件装载类信息
            }catch (ClassNotFoundException e) { 
                e.printStackTrace();
            }
            return null;
        } 
    }

    json工具类:

    package light.zhang.ioc.utils;
     
    
    import java.io.InputStream;
    import java.text.SimpleDateFormat;
    
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.MapperFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializationFeature;
    
    public class JsonUtils {
    
        private static final ObjectMapper mapper = new ObjectMapper();
    
        private JsonUtils() {
        }
    
        public static ObjectMapper getObjectMapper() {
            return mapper;
        }
    
        public static <T> T readValue(String json, Class<T> cls) {
            try {
                return mapper.readValue(json, cls);
            } catch (Exception var3) {
                return null;
            }
        }
    
        public static <T> T readValue(InputStream is,Class<T> cls){
            try{
                return mapper.readValue(is,cls);
            }catch (Exception e){
                return null;
            }
        }
    
        public static <T> T readValue(byte[] bytes, Class<T> cls) {
            try {
                return mapper.readValue(bytes, cls);
            } catch (Exception var3) {
                return null;
            }
        }
    
        public static <T> T readValue(String json, TypeReference<?> valueTypeRef) {
            try {
                return mapper.readValue(json, valueTypeRef);
            } catch (Exception var3) {
                return null;
            }
        }
    
        public static <T> T readValue(byte[] bytes, TypeReference<?> valueTypeRef) {
            try {
                return mapper.readValue(bytes, valueTypeRef);
            } catch (Exception var3) {
                return null;
            }
        }
    
        public static <T> T readValue(InputStream is,TypeReference<?> valueTypeRef){
            try{
                return mapper.readValue(is,valueTypeRef);
            }catch (Exception e){
                return null;
            }
        }
        public static String writeValue(Object entity) {
            try {
                return mapper.writeValueAsString(entity);
            } catch (Exception var2) {
                return null;
            }
        }
    
        public static byte[] writeByteValue(Object entity) {
            try {
                return mapper.writeValueAsBytes(entity);
            } catch (Exception var2) {
                return null;
            }
        }
    
        static {
            mapper.enable(SerializationFeature.INDENT_OUTPUT);
            mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
            mapper.setSerializationInclusion(JsonInclude.Include.USE_DEFAULTS);
            mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
            mapper.getDeserializationConfig().withoutFeatures(new DeserializationFeature[]{DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES});
            mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, true);
            mapper.configure(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING,true);
            mapper.configure(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS, true); 
            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
            mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }
    
    }

    反射类:

    package light.zhang.ioc.utils;
    
    import java.lang.reflect.Field;
    
    /**
     * 主要通过 Java 的反射原理来完成对象的信息注入
     * @author witts
     */
    public class ReflectionUtils {
            /**
             * 初始化参数信息
             * @param field
             * @param key
             * @param val
             * @throws IllegalAccessException
             */
            public static void initParamter(Field field,Object key,Object val) throws IllegalAccessException {
                if(null !=field) {
                    field.setAccessible(Boolean.TRUE);
                    field.set(key, val);//注入参数信息
                }
            }
    }

    客户端调用

    package light.zhang.ioc.test;
    
    import junit.framework.TestCase;
    import light.zhang.ioc.client.JsonApplicationContext;
    import light.zhang.ioc.core.ApplicationContext;
     
    /**
     * 模拟spring ioc对象创建管理销毁
     * @author witts
     *
     */
    public class AppTest extends TestCase {
        
         private static final ApplicationContext applicationContext=new JsonApplicationContext("application.json"); //读取配置文件
         
         public static void main(String[] args)   { 
            try { 
                Robot aiRobot; aiRobot =  (Robot) applicationContext.getBean("robot");//获取对象
                aiRobot.show();//调用对象功能
            } catch (Exception e) { 
                e.printStackTrace();
            }  
        }
    }

    需要被管理的对象

    package light.zhang.ioc.test;
    
    public class Hand {
        public void waveHand(){
            System.out.println("hand out message");
        }
    }
    package light.zhang.ioc.test;
    
    public class Mouth {
        public void speak(){
            System.out.println("Mouth out message");
        }
    }
    package light.zhang.ioc.test;
     
    public class Robot {
         //需要注入 hand 和 mouth,容器自动注入对象并实例化
        private Hand hand;
        private Mouth mouth;
        
        public void show(){
            hand.waveHand();
            mouth.speak();
        }
    }

    主要是理解spring ioc的加载-实例-注册-销毁等一系列的对象生命周期管理,我这里只是模仿一下spring对对象的加载,创建,注册 对象销毁是个复杂的过程,并不是那么容器就模拟出来的,

    spring管理的对象方式有很多种,

    本来是由应用程序管理的对象之间的依赖关系,现在交给容器管理,这就是控制反转,及交给Ioc容器。Spring的IoC主要使用DI方式实现,

    不需要主动查找,对象的查找、定位和创建全部由容器管理。spring中有三种注入方式,一种是set注入,一种是接口注入,另一种是构造方法注入

  • 相关阅读:
    Feign原理 (图解)
    纠错:Feign 没用 短连接
    【转】linux 查看哪些进程用了swap
    【转】交换分区SWAP
    【改】linux中分区的概念
    【转】SPI FLASH与NOR FLASH的区别 详解SPI FLASH与NOR FLASH的不一样
    【转】DDR3和eMMC区别
    ARP (地址解析协议)
    【转】一文搞懂C语言回调函数
    【改】shell 判断文件中有无特定子串方法(grep)
  • 原文地址:https://www.cnblogs.com/light-zhang/p/8390885.html
Copyright © 2020-2023  润新知