首页 > 其他分享 >反射、工厂模式、IOC容器浅尝 一篇入门

反射、工厂模式、IOC容器浅尝 一篇入门

时间:2022-12-10 16:12:04浏览次数:61  
标签:入门 clazz 浅尝 获取 import 工厂 IOC class String

反射

什么是反射?

个人目前理解:反射是在程序运行期间获取class信息,用这些信息做一些操作,例如本文后续要用的实例化一个对象以及为属性赋值。

如何获取class信息

  1. 调用对象的getClass方法
  2. 调用类的class属性
  3. 使用Class类中的forName()静态方法(最安全,性能最好)即:Class.forName(“类的全路径”)

常用方法

//获取包名、类名
clazz.getPackage().getName()//包名
clazz.getSimpleName()//类名
clazz.getName()//完整类名
 
//获取成员变量定义信息
getFields()//获取所有公开的成员变量,包括继承变量
getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量
getField(变量名)
getDeclaredField(变量名)
 
//获取构造方法定义信息
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)
 
//获取方法定义信息
getMethods()//获取所有可见的方法,包括继承的方法
getMethod(方法名,参数类型列表)
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)
 
//反射新建实例
clazz.newInstance();//执行无参构造创建对象
clazz.newInstance(222,"韦小宝");//执行有参构造创建对象
clazz.getConstructor(int.class,String.class)//获取构造方法
 
//反射调用成员变量
clazz.getDeclaredField(变量名);//获取变量
clazz.setAccessible(true);//使私有成员允许访问
f.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null
f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null
 
//反射调用成员方法
Method m = Clazz.getDeclaredMethod(方法名,参数类型列表);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(实例,参数数据);//让指定实例来执行该方法

工厂模式简要介绍

推荐先观看最通俗易懂的讲解工厂模式

什么是工厂模式

个人简单的理解:工厂模式是建造者模式,为用户屏蔽了实例化对象的一些细节,可以为用户做一些数据转换等工作(对用户屏蔽),防止用户滥用构造函数,应用十分广泛,如单例模式也是使用了这个思想。

三种工厂模式简单介绍(其实就两种)

  1. 简单工厂模式:一个工厂类,提供一个静态方法,为用户生成对象,多态的时候使用。
  2. 工厂方法模式:提供一个抽象方法,这样是为了纠正简单工厂的缺点(简单工厂在扩展的时候会违反开闭原则)。工厂方法模式在扩展的时候只需要继承抽象基工厂即可。
  3. 抽象工厂模式:其实是有多个抽象方法,可以生成不同大类的产品,不过它扩展大类产品的时候还是要修改基类,违反了开闭原则。当抽象工厂模式只有一个产品体系的话就会退化成工厂方法模式。

IOC

简介

IOC:控制反转,我们不再需要主动的new对象,而是被动的接受对象。将对象交给容器管理,然后容器通过工厂模式为我们用户提供对象。

将以上三种技术结合起来实现一个简易的IOC容器

首先写一个普通类People

public class People {
    private String name;
    private String age;

    @Override
    public String toString() {
        return "name: "+ name + "age: "+ age;
    }
}

写一个beans.xml,将我们的普通类注册进去

<?xml version="1.0" encoding="utf-8" ?>
<xml>
    <bean id="people" class="People">
        <property name="name">翔掌门</property>
        <property name="age">18</property>
    </bean>
</xml>

写一个工厂BeanFactory

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class BeanFactory {
    // 底层是一个hashmap
    private static HashMap<String,Object> beanMap = new HashMap<>();
    public static Object getBean(String id) {
        return beanMap.get(id);
    }
    static {
        try {
            init();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (SAXException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    // 在这里完善hashmap
    private static void init() throws ParserConfigurationException, IOException, SAXException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse("resource/beans.xml");
        NodeList beans = document.getElementsByTagName("bean");
        for (int i = 0; i < beans.getLength(); i++) {
            // 获取<bean>
            Element bean = (Element) beans.item(i);
            // 将这个bean的属性先存储起来
            Map<String,String> attrs = getAttrs(bean.getChildNodes());
            // 反射获取类信息
            Class<?> clazz = Class.forName(bean.getAttribute("class"));
            Object instance = clazz.newInstance();
            Field[] fields = clazz.getDeclaredFields();
            for (int j = 0; j < fields.length; j++) {
                Field field = fields[j];
                // 让私有变量可以访问
                field.setAccessible(true);
                // filed的名字就是示例变量的名字
                field.set(instance,attrs.get(field.getName()));
            }
            // 变量设置完毕
            beanMap.put(bean.getAttribute("id"),instance);
        }
    }

    private static Map<String, String> getAttrs(NodeList childNodes) {
        Map<String,String> map = new HashMap<>();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);

            if(node.getNodeType() == Node.ELEMENT_NODE) {
                Element el = (Element) node;
                String key = el.getAttribute("name");
                String value = el.getFirstChild().getNodeValue();
                map.put(key,value);
            }
        }
        return map;
    }
}

核心就是getBean方法和beanMap。

加载工厂类的时候,将beans.xml解析,获取所有对象以及属性,通过反射构造对象,放在beanMap中。

运行

public class Demo2 {
    public static void main(String[] args) {
        Object people = BeanFactory.getBean("people");
        System.out.println(people);
    }
}

标签:入门,clazz,浅尝,获取,import,工厂,IOC,class,String
From: https://www.cnblogs.com/xjlwl/p/16971753.html

相关文章

  • Mybatis 入门实战(4)--Mybatis-Plus 使用
    ​​MyBatis-Plus​​​ 是一个 ​​MyBatis​​ 的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。本文主要介绍Mybatis-Plus的基本使用,相关......
  • Halcon 快速入门教程
    ​​前言​​​​一,HALCON概述​​​​1.1,HALCON安装​​​二,HALCON架构​​2.1,算子​​​2.1.1,参数和数据结构​​​​2.2,拓展包​​​2.3,接口​​​2.3.1,HALCON-Python......
  • spring——控制反转(IoC)—— 与 ——依赖注入(DI)
    控制反转(IoC)  在传统的Java应用中,一个类想要调用另一个类中的属性或方法,通常会先在其代码中通过newObject()的方式将后者的对象创建出来,然后才能实现属性或方法......
  • django极速入门指南-02
    内容概要静态文件配置request对象方法pycharm连接MySqldjango连接MySqldjango模型层初识基本ORM操作静态文件配置1.静态文件 指的是不怎么经常变化的文件,主要......
  • 【大数据入门核心技术-HBase】(七)HBase Python API 操作
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • JavaScript入门⑩-ES6归纳总结
    JavaScript入门系列目录JavaScript入门①-基础知识筑基JavaScript入门②-函数(1)基础{浅出}JavaScript入门③-函数(2)原理{深入}执行上下文JavaScript入门④-万物皆......
  • 极客编程python入门-匿名函数
    当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。在Python中,对匿名函数提供了有限支持。>>>list(map(lambdax:x*x,[1,2,3,4,5,6,7,8......
  • 卷积神经网络入门
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • 前端入门学习笔记四十七
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • 前端入门学习笔记四十五
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......