Resorte del marco (8) - doscientos líneas de código para sencilla contenedor IoC

I. Introducción

La primavera tiene dos funciones importantes, una AOP (Programación Orientada a Aspectos), el principal uso de la tecnología de agente dinámico

Fundamentos de Java (9) - que refleja el agente dinámico

Segundo COI (Inversión de Control) técnica. Inversión de Control se creará objeto de derechos al contenedor primavera COI para gestionar, los desarrolladores sólo tienen que centrarse en crear una clase de nivel superior, sin tener en cuenta las diversas dependencias subyacentes clase crear una relación, pero se entregó a la primavera COI para crear.

La técnica utilizada en el presente documento, el modo de análisis sintáctico reflectante técnicas + perfil dom4j + xml simple operación de la COI, forma utilizando el método de inyección de setter el COI analógica.

II. Cronograma

Finalmente, ejemplo de operación de la obtención de la reflexión se consiguen por XmlApplicationContext; BeanUtils para analizar la configuración de XML, y configurar el mapeo y la propiedad de la haba Bueno
Aquí Insertar imagen Descripción

III. La implementación del Código

  • Código de la estructura general del
    código del núcleo se encuentra XmlApplicationContext y BeanUtils, un total de más de doscientas líneas de código
    Aquí Insertar imagen Descripción

  • habas bolsa de
    frijol bolsa de frijoles para almacenar la dirección requerida por el COI

/**
 * @Auther: ARong
 * @Date: 2020/2/13 12:51 下午
 * @Description: Person类
 */
@Data
@ToString
public class Person {
    private String name;
    private Student student;
    public Person() {
        System.out.println(new Date() + ":Person类被创建");
    }
}


/**
 * @Auther: ARong
 * @Date: 2020/2/13 12:55 下午
 * @Description: Student类
 */
@Data
@ToString
public class Student {
    private String name;
    public Student() {
        System.out.println(new Date() + ":Student类被创建");
    }
}
  • paquete XML
    almacenado bajo el paquete xml applicationContext.xml, COI contenedor donde todas las clases y dispuestos para registrar
<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <bean name="person" class="spring_demo.my_ioc.beans.Person" scope="prototype">
        <properties>
            <property name="name" value="ARong"/>
            <property name="student" ref="student"/>
        </properties>
    </bean>

    <bean name="student" class="spring_demo.my_ioc.beans.Student">
        <properties>
            <property name="name" value="XiaoMing"/>
        </properties>
    </bean>

</beans>
  • utils
    los define paquete utils propiedad y Bean, son necesarios para describir la información de clase de frijoles y la información de atributos, el programa utiliza un bean de instancia creada fácilmente reflectante

  • Frijol

/**
 * @Auther: ARong
 * @Date: 2020/2/13 1:00 下午
 * @Description: 描述对象实例的抽象Bean
 */
@Data
@ToString
public class Bean {
    private String name;// 类名
    private String classpath;// 类全限定路径
    private String scope = "singleton";// 默认单例
    private List<Property> properties = new ArrayList<>();// 所含属性
}
  • Propiedad
/**
 * @Auther: ARong
 * @Date: 2020/2/13 1:03 下午
 * @Description: 描述类所含属性的抽象
 */
@Data
@ToString
public class Property {
    private String name;// 属性名
    private String value;// 属性值
    private String ref;// 引用对象
}

Además, BeanUtils para el envasado de configuración para el xml información analizada

  • BeanUtils
/**
 * @Auther: ARong
 * @Date: 2020/2/13 1:09 下午
 * @Description: Bean操作的工具类
 */
public class BeanUtils {
    public static final BeanUtils DEFAULT = new BeanUtils();
    private BeanUtils() {}

    /*
     * @Author ARong
     * @Description 使用dom4j解析xml文件内容,封装对应的bean与相应属性
     * @Date 2020/2/13 1:12 下午
     * @Param [xmlPath]
     * @return java.util.Map<java.lang.String,spring_demo.my_ioc.utils.Bean>
     **/
    public Map<String, Bean> getBeanConfig(String xmlPath) {
        HashMap<String, Bean> map = new HashMap<>();
        SAXReader saxReader = new SAXReader();
        Document document = null;
        try {
            document = saxReader.read(xmlPath);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        Iterator<Element> beans = document.getRootElement().elementIterator();
        while (beans.hasNext()) {
            Element beanElement = beans.next();
            // 封装bean
            Bean bean = new Bean();
            bean.setName(beanElement.attributeValue("name"));
            bean.setClasspath(beanElement.attributeValue("class"));
            String scope = beanElement.attributeValue("scope");
            if (scope != null) {
                bean.setScope(scope);
            }
            // 封装属性
            ArrayList<Property> proList = new ArrayList<>();
            Iterator<Element> properties = beanElement.element("properties").elementIterator();
            while (properties.hasNext()) {
                Element propertyElement = properties.next();
                Property property = new Property();
                property.setName(propertyElement.attributeValue("name"));
                String value = propertyElement.attributeValue("value");
                String ref = propertyElement.attributeValue("ref");
                if (value != null) {
                    property.setValue(value);
                }
                if (ref != null) {
                    property.setRef(ref);
                }
                proList.add(property);
            }
            bean.setProperties(proList);
            map.put(bean.getName(), bean);
            // System.out.println(bean);
        }
        return map;
    }

}
  • contexto paquete
    paquete contexto define la interfaz y implementación de la clase XmlApplicationContext BeanFactory, por ejemplo tal como se obtiene por el contenedor COI y clase método getBean
  • BeanFactory
public interface BeanFactory {
    /*
     * @Author ARong
     * @Description 根据name获取对象的实例
     * @Date 2020/2/13 1:57 下午
     * @Param [name]
     * @return java.lang.Object
     **/
    Object getBean(String name);
}
  • XmlApplicationContext
/**
 * @Auther: ARong
 * @Date: 2020/2/13 2:03 下午
 * @Description:
 */
@Data
public class XmlApplicationContext implements BeanFactory {
    private Map<String, Bean> beanMap;
    private static final Map<String, Object> context = new HashMap<>();

    private XmlApplicationContext() {
    }

    public XmlApplicationContext(String xmlPath) {
        beanMap = BeanUtils.DEFAULT.getBeanConfig(xmlPath);
        // 将单例对象先创建并放入context中
        Set<Map.Entry<String, Bean>> entries = beanMap.entrySet();
        for (Map.Entry<String, Bean> entry : entries) {
            String key = entry.getKey();
            Bean value = entry.getValue();
            if ("singleton".equals(value.getScope())) {
                context.put(key, createBean(value));
            }
        }
    }

    /*
     * @Author ARong
     * @Description 通过beanName获取Object
     * @Date 2020/2/13 2:08 下午
     * @Param [name]
     * @return java.lang.Object
     **/
    @Override
    public Object getBean(String name) {
        Object instance = context.get(name);
        if (instance == null) {
            // 未创建的多例对象,每次都新创建
            instance = createBean(beanMap.get(name));
        }
        return instance;
    }

    /*
     * @Author ARong
     * @Description 通过反射创建相应的对象
     * @Date 2020/2/13 2:13 下午
     * @Param [name, beanMap, context]
     * @return java.lang.Object
     **/
    public Object createBean(Bean bean) {
        // 获取类全限定名
        String classpath = bean.getClasspath();
        Class<?> beanClass = null;
        try {
            beanClass = Class.forName(classpath);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        // 创建class对象实例
        Object beanInstance = null;
        try {
            beanInstance = beanClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        // 获得Bean的属性,将其注入
        if(bean.getProperties() != null){
            for(Property prop : bean.getProperties()){
                // 获得要注入的元素名称
                String proName = prop.getName();
                // 根据属性名称获得对应属性的set方法
                Method setMethod = getSetMethod(beanInstance, proName);

                Object param = null;
                if(prop.getValue() != null){
                    // value属性注入
                    param = prop.getValue();

                }
                if(prop.getRef() != null){
                    // bean引用注入
                    //要注入其他bean到当前bean中,先从容器中查找,当前要注入的bean是否已经创建并放入容器中
                    Object existBean = context.get(prop.getRef());
                    if(existBean == null){
                        // 容器中不存在要注入的bean,创建该bean
                        existBean = createBean(beanMap.get(prop.getRef()));
                        // 将创建好的单例bean放入容器中
                        if("singleton".equals(beanMap.get(prop.getRef()).getScope())) {
                            context.put(prop.getRef(), existBean);
                        }
                    }
                    param = existBean;
                }

                try {
                    // 调用set方法注入该属性
                    setMethod.invoke(beanInstance, param);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
        return beanInstance;
    }

    /*
     * @Author ARong
     * @Description 通过反射获取到实例的变量setter方法
     * @Date 2020/2/13 2:32 下午
     * @Param [beanInstance, proName]
     * @return java.lang.reflect.Method
     **/
    private Method getSetMethod(Object beanInstance, String proName) {
        Class<?> beanClass = beanInstance.getClass();
        Method setterMathod = null;
        // 先获取方法参数类型
        Class<?> type = null;
        try {
            type = beanClass.getDeclaredField(proName).getType();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        String begin = proName.substring(0, 1).toUpperCase();
        String methodName = "set" + begin + proName.substring(1);
        // 获取setter方法
        try {
            setterMathod  = beanClass.getDeclaredMethod(methodName, type);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return setterMathod;
    }
}
  • paquete de prueba
    para las pruebas simples COI
  • TestIOC
/**
 * @Auther: ARong
 * @Date: 2020/2/13 1:24 下午
 * @Description: 测试IOC容器
 */
public class TestIoC {
    @Test
    public void testIOC() {
        // 1.初始化IOC容器
        System.out.println("==========1.初始化IOC容器==========");
        XmlApplicationContext context = new XmlApplicationContext("/Users/arong/MyFile/Project/Algorithm/src/main/java/spring_demo/my_ioc/xml/applicationContext.xml");

        // 2.测试注入在Student中注入name属性
        System.out.println("==========2.测试注入在Student中注入name属性==========");
        testGetBean1(context);

        // 3.测试在Person中注入student引用以及name属性
        System.out.println("==========3.测试在Person中注入student引用以及name属性==========");
        testGetBean2(context);

        // 4.测试Person对象是否为多例、Student对象是否为单例
        System.out.println("==========4.测试Person对象是否为多例、Student对象是否为单例==========");
        testGetBean3(context);
    }



    private void testGetBean1(XmlApplicationContext context) {
        Student student = (Student) context.getBean("student");
        System.out.println(student+"\n");
    }

    private void testGetBean2(XmlApplicationContext context) {
        Person person = (Person) context.getBean("person");
        System.out.println(person+"\n");
    }

    private void testGetBean3(XmlApplicationContext context) {
        Student student1 = (Student) context.getBean("student");
        Student student2 = (Student) context.getBean("student");
        System.out.println("student1 == student2:" + (student1 == student2));
        Person person1 = (Person) context.getBean("person");
        Person person2 = (Person) context.getBean("person");
        System.out.println("person1 == person2:"+(person1 == person2));
    }

La visualización de salida, la COI función básica es normal, dos cientos de líneas de código es el código del núcleo de la COI. Frijol ejemplo concreto de cómo gestionar el ciclo de vida? Y la forma de anotaciones de configure método de exploración se refina aún más ~
Aquí Insertar imagen Descripción

Publicados 309 artículos originales · ganado elogios 205 · Vistas de 300.000 +

Supongo que te gusta

Origin blog.csdn.net/pbrlovejava/article/details/104297340
Recomendado
Clasificación