IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> IOC与DI -> 正文阅读

[移动开发]IOC与DI

IOC-Inversion of Control-控制反转

controller,service,DAO层之间的问题

controller,service,DAO在这三层之间调用时,以前都是通过直接new下层实现类的对象,

在controller层中用UserService? userService = new UserService();

这就导致上层和下层的依赖很强,如果删除下层的话,上层会报错。

系统架构的设计原则是高内聚,低耦合。那如何实现控制反转呢?

1.将原先的直接创建对象的方式摒弃,如在service层中不直接newDAO的对象,而是不赋值。

2.将类之间的关系写在配置文件中。

bean表示这个类,property表示类中的属性,这个属性是自定义的类。

其中全类名是controller的bean中,id值是用来被请求识别的。

全类名是Service,DAO的,id值是被属性的ref识别的。

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE beans [
        <!ELEMENT beans (bean*)>
        <!ELEMENT bean (property*)>
        <!ELEMENT property (#PCDATA)>

        <!ATTLIST bean id ID #REQUIRED>
        <!ATTLIST bean class CDATA #IMPLIED>
        <!ATTLIST property name CDATA #IMPLIED>
        <!ATTLIST property ref IDREF #IMPLIED>
        ]>
<!--        IMPLIED 表示可有可无-->
<beans>
    <bean id="userBasicDAO" class="DAO.impl.UserBasicDAOImpl"/>
    <bean id="topicDAO" class="DAO.impl.TopicDAOImpl"/>

    <bean id="userBasicService" class="service.impl.UserBasicServiceImpl">
        <property name="userBasicDAO" ref="userBasicDAO"/>
    </bean>

    <bean id="topicService" class="service.impl.TopicServiceImpl">
        <property name="topicDAO" ref="topicDAO"/>
    </bean>

    <bean id="user" class="controller.UserController">
        <property name="userBasicService" ref="userBasicService"/>
        <property name="topicService" ref="topicService"/>
    </bean>
    <bean id="page" class="myssm.myspringmvc.PageController"/>
    
</beans>

3.将所有的bean加载到Map集合中

形成了这样的对应关系:String:类

userBasic:UserBasicDAOImpl类

user:UserController对象

....

4.直接通过这个方法给属性赋值,这个成为依赖注入(DI-dependency injection)

public class ClassPathXmlApplicationContext implements BeanFactory {

    //保存每个bean的id和对应的实例对象
    private Map<String,Object> beanMap = new HashMap<>();
    private String path = "applicationContext.xml" ;
    //利用这个无参构造器去调用下面的有参构造器
    public ClassPathXmlApplicationContext(){
        this("applicationContext.xml");
    }
    public ClassPathXmlApplicationContext(String path){
        if(StringUtil.isEmpty(path)){
            throw new RuntimeException("IOC容器的配置文件没有指定...");
        }
        try {
            //1.加载xml配置文件,目的是获取xml文件中id和class属性的对应关系并保存到map集合中
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path);
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            //2.获取到xml文件的对象
            Document document = documentBuilder.parse(inputStream);
            //3.获取xml文件中所有的bean标签对象,放到list集合中
            NodeList beanNodeList = document.getElementsByTagName("bean");
            //4.遍历每个bean标签对象,将其属性id和class保存到map中
            for(int i = 0 ; i<beanNodeList.getLength() ; i++){
                //4.1获取每一个bean标签对象
                Node beanNode = beanNodeList.item(i);
                //4.2这行代码先不管,是为了用Element类中的方法
                if(beanNode.getNodeType() == Node.ELEMENT_NODE){
                    Element beanElement = (Element)beanNode;
                    //4.3获取bean标签的属性
                    String beanId =  beanElement.getAttribute("id");
                    String className = beanElement.getAttribute("class");
                    //4.4class属性是字符串,转为对应的类
                    //4.4.1用全类名获取Class对象,controller层,service层,DAO层类和对应的id都放了进去
                    Class beanClass = Class.forName(className);
                    //4.4.2创建bean实例
                    Object beanObj = beanClass.newInstance() ;
                    //4.5将bean实例对象保存到map容器中
                    beanMap.put(beanId , beanObj);
                }
            }

            //设置bean和bean之间的依赖关系
            for(int i = 0 ; i<beanNodeList.getLength() ; i++){
                Node beanNode = beanNodeList.item(i);
                if(beanNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element beanElement = (Element) beanNode;
                    String beanId = beanElement.getAttribute("id");
                    //以上是先获取到xml文件每个bean的id
                    //获取bean节点的子节点,子节点包括注释,换行和空格,元素节点
                    NodeList beanChildNodeList = beanElement.getChildNodes();
                    //获取bean节点的总共的子节点进行循环
                    for (int j = 0; j < beanChildNodeList.getLength() ; j++) {
                        //获取到每个子节点
                        Node beanChildNode = beanChildNodeList.item(j);
                        //如果这个子节点是元素节点并且元素名等于property
                        if(beanChildNode.getNodeType()==Node.ELEMENT_NODE && "property".equals(beanChildNode.getNodeName())){
                            //将子节点转为Element类型,是为了使用getAttribute方法
                            Element propertyElement = (Element) beanChildNode;
                            //获取到子节点的属性
                            String propertyName = propertyElement.getAttribute("name");
                            String propertyRef = propertyElement.getAttribute("ref");
                            //接下来要根据ref对应具体bean的id然后找到对象,再给name对象赋值
                            //(1)找到ref对应的实例
                            Object refObj = beanMap.get(propertyRef);
                            //(2)找到当前bean(不是子节点)的类
                            Object beanObj = beanMap.get(beanId);
                            Class beanClazz = beanObj.getClass();
                            //(3)找到这个类中的下层属性
                            Field propertyField = beanClazz.getDeclaredField(propertyName);
                            //(4)给这个属性赋值
                            propertyField.setAccessible(true);
                            propertyField.set(beanObj,refObj);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object getBean(String id) {
        return beanMap.get(id);
    }
}

5.上面的这个内容写在构造方法里。

在dispatcher的init方法中创建BeanFactory的对象,就自动将controller,service中的属性赋值了。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:32:51  更:2022-04-01 23:34:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 19:30:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码