首页 > 其他分享 >Spring系列之(一)Spring概述

Spring系列之(一)Spring概述

时间:2024-02-27 20:57:34浏览次数:66  
标签:依赖 系列 配置文件 对象 Spring static 概述 props import

Spring 概述

1. 程序的耦合

耦合:程序间的依赖关系
解耦:降低程序间的依赖关系
分类

  1. 类之间的依赖
  2. 方法之间的依赖

2. 类之间的依赖问题的实例

2.1 JDBC操作数据库存在的耦合问题

首先正常编写一个jdbc查询操作的类

package com.itheima.jdbc;

import java.sql.*;

public class JDBCDemo {

    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //2. 获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://xxx", "root", "123456");
        //3. 获取操作的数据库的预处理对象
        PreparedStatement preparedStatement = connection.prepareStatement("select * from account");
        //4. 执行SQL,得到结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        //5. 遍历结果集
        while (resultSet.next()){
            System.out.println(resultSet.getString("money"));
        }
        //6. 释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

查询结果是正常的
在这里插入图片描述

很容易看出在注册驱动时,这个类是依赖于com.mysql.jdbc.Driver这个类的,这就是类之间的依赖问题,那这种情况下会导致什么问题出现呢

试想,假如com.mysql.jdbc.Driver这个类不存在,那么程序在编译期就会报错
在这里插入图片描述
我们期望的是,编译期是正常进行的,直到程序执行时才报错。
注册驱动时做如下修改
在这里插入图片描述
可以看到编译期是正常进行的,这样就做到了编译期不依赖,运行期才依赖,这里就用到了反射。

2.2 解耦的思路

  1. 使用反射来创建对象,而避免用new关键字
    但是使用反射传入的字符串在上述的例子中是写死的,这样如果更改驱动就需要修改代码,于是就引出了第二条思路
  2. 通过读配置文件来获取要创建的对象全限定类名

有了这两条思路,再来看下实际的Web开发中一个类之间依赖的实例

2.3 Web开发中的类之间依赖的实例

在这里插入图片描述
表现层
在这里插入图片描述
业务层
在这里插入图片描述
持久层
在这里插入图片描述
在上述过程中,表现层和业务层都通过new关键字获取到了下层的对象,这也是类之间的依赖问题,也就是耦合问题。
那我们的思路跟JDBC注册驱动是一样的,反射和配置文件结合,从而引出了工厂模式。

  1. 需要一个配置文件来配置需要创建的service和dao
    配置的内容:唯一标识=全限定类名(key=value)
  2. 通过读取配置文件中配置的内容,反射创建对象
    配置文件可以是xml,也可以是properties

2.4 工厂模式解耦

  1. 创建配置文件,对应解耦思路的第二条,通过读配置文件来获取要创建的对象全限定类名,这个配置文件的内容就是用来配置用于获取指定类对象的标识和指定类对象的全限定类名。
    在这里插入图片描述
  2. 单独创建一个工厂类,用于解析配置文件,能够根据调用者给出的标识获取到标识对应的全限定类名,同时通过反射拿到该类的对象,并返回给调用者
package com.itheima.factory;

import java.io.InputStream;
import java.util.Properties;

public class Factory {
    private static Properties props;

    static {
        try {
            //生成一个properties文件实例
            props = new Properties();
            InputStream in = Factory.class.getClassLoader().getResourceAsStream("factory.properties");
            //加载我们自己的配置文件
            props.load(in);
        }catch (Exception e){
            throw new ExceptionInInitializerError("初始化properties失败");
        }
    }
    
    /**
     *
     * @param name 配置文件中的标识,用于获取指定类的全限定类名
     * @return
     */
    public static Object getBean(String name){
        //bean 要返回给调用者的对象,后面是通过反射创建出来的
        Object bean = null;
        try {
            //根据标识获取到标识对应的全限定类名
            String property = props.getProperty(name);
            //根据解析出来的全限定类名通过反射得到指定的类并生成该类的一个对象
            bean = Class.forName(property).newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        //将反射生成的对象返回给调用者
        return bean;
    }
}

  1. 修改表现层和业务层的代码
    业务层
    在这里插入图片描述
    表现层
    在这里插入图片描述

至此,就实现了Web实际开发中的编译期不依赖,运行期才依赖

2.5 工厂模式改进

上述的工厂模式中,其实是多例的,就是调用一次产生一个新的对象,那么,如何实现单例的工厂模式呢
思路是这样的:
工厂类在初始化时,将配置文件中涉及的所有类都创建一个对象,将对象存入仓库,调用者需要对象的时候直接从仓库取即可。
持久层、业务层、表现层的代码不用动,只修改工厂类的静态代码块和方法即可

package com.itheima.factory;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class Factory {
    private static Properties props;
    private static Map<String, Object> ck;

    static {
        try {
            //生成一个properties文件实例
            props = new Properties();
            InputStream in = Factory.class.getClassLoader().getResourceAsStream("factory.properties");
            //加载我们自己的配置文件
            props.load(in);
            //实例化一个仓库
            ck = new HashMap<String, Object>();
            //获取配置文件中的所有键
            Enumeration keys = props.keys();
            //根据键遍历所有值,为每个值通过反射实例化对象并存入仓库
            while (keys.hasMoreElements()){
                String s = keys.nextElement().toString();
                String property = props.getProperty(s);
                Object o = Class.forName(property).newInstance();
                ck.put(s, o);
            }
        }catch (Exception e){
            throw new ExceptionInInitializerError("初始化properties失败");
        }
    }
    public static Object getBean(String name){
        //调用者调用时直接返回仓库中的对象
        return ck.get(name);
    }
}

至此,就实现了单例的工厂模式

3. IOC 控制反转

被动接收方式获取对象的思想就是控制反转
在这里插入图片描述
补充:工厂模式中iUserDao获取对象就是被动接收的

4. Spring中的一些概念

组件:对应到Web应用中,就是Web应用的每一个部分,比如表现层,业务层,持久层
Bean:可重用组件
JavaBean:用Java语言编写的可重用组件
注:JavaBean的范围大于实体类的范围,像Service、Dao等一切可重用的组件都是JavaBean的范畴
容器:即工厂模式中的工厂

maven工程的配置文件是放在resource下的,resource在编译后会放到class目录下
单例对象有线程问题(类的成员变量)
表现层 请求参数封装
IOC:解决程序间的依赖关系
持久层:Dao
业务层:Service
表现层:Controller

标签:依赖,系列,配置文件,对象,Spring,static,概述,props,import
From: https://www.cnblogs.com/wzzzj/p/18038221

相关文章

  • spring boot 中使用MybatisPlus的自动填充createTime和updateTime
    首先需要在实体类的字段上加上注解,并且将类型更改为LocalDateTime@TableField(fill=FieldFill.INSERT)@JsonInclude(value=JsonInclude.Include.NON_NULL)@JsonFormat(pattern="yyyy-MM-ddHH:mm:ss")privateLocalDateTimecreateTime;@TableFie......
  • springboot学习过程中的特殊错误
     这是我在学习使用springboot过程中遇到的一个小问题,询问了gpt但是并没有解决我的报错,在网上浏览信息后最终知道了是哪里出了问题 就如这个好哥哥说的一样,mybatis自带的方法不会出现问题,所以问题出在了实体类定义上面,加了@Tableld的注解就解决了问题。......
  • 简单看下最近的Spring Secrurity、Spring漏洞(CVE-2024-22234、CVE-2024-22243)
    最近的这两个cve我看国内很多情报将其评为高危,所以想着去看看原理,看完发现都比较简单,利用要求的场景也相对有限(特别是第一个),所以就随便看下就行了SpringSecurity用户认证绕过(CVE-2024-22234)先看下官网的公告(https://spring.io/security/cve-2024-22234)InSpringSecurit......
  • spring重点后置处理器
    1.DefaultListableBeanFactory的作用:默认实现了ListableBeanFactory和BeanDefinitionRegistry接口,基于beandefinition对象,是一个成熟的beanfactroy。最典型的应用是:在访问bean前,先注册所有的definition(可能从beandefinition配置文件中)。使用预先建立的bean定义元数......
  • Windows系统概述及磁盘分区
    Windows系统概述及磁盘分区Windows系统概述Windows系统作为世界上使用者最多,最受欢迎的操作系统,值得热爱者们进行详细的研究.我们将分别介绍Windows系统的安装,维护,优化,以及进阶的高级操作.本教程所有的操作均使用Windows10Professional操作系统.磁盘分区有关磁盘的知......
  • springboot 统一处理请求非法参数
    通过拦截器和过滤器实现,话不多说上代码。1、重写HttpServletRequestWrapper读取body里面的内容。publicclassRequestWrapperextendsHttpServletRequestWrapper{privatefinalStringbody;publicRequestWrapper(HttpServletRequestrequest){super......
  • Java基础-面向对象概述
    本章重点针对面向对象的三大特征:继承、封装、多态进行详细的讲解。另外还包括抽象类、接口、内部类等概念。很多概念对于初学者来说,更多的是先进性语法性质的了解。1.面向对象-继承:1.继承的实现:继承通过如下格式实现:class子类名extends父类名[implements<接口名>]{}......
  • 如何创建自己的Spring Boot Starter并为其编写单元测试
    当我们想要封装一些自定义功能给别人使用的时候,创建SpringBootStarter的形式是最好的实现方式。如果您还不会构建自己的SpringBootStarter的话,本文将带你一起创建一个自己的SpringBootStarter。快速入门创建一个新的Maven项目。第三方封装的命名格式是xxx-spring-boo......
  • 面试题以及一些问题概述
    1数据库三大范式是什么数据库的三大范式是指关系数据库设计中的三个规范化级别,用于规范化数据库中的数据结构,提高数据的一致性和减少数据冗余。这三大范式分别是:1.第一范式(1NF):要求数据库表中的每个字段都是原子性的,不可再分。也就是说,每个字段中的数据不能包含多个值或多个属......
  • springboot2.6开始禁止循环依赖了
    参考文章: https://mp.weixin.qq.com/s?__biz=MzI0MTUwOTgyOQ==&mid=2247497189&idx=1&sn=0f03cdafad9bacef66c64a490b85ff23&scene=21#wechat_redirect使用了SpringBoot2.6及以上版本的,如果要允许循环依赖,可以作如下设置:方案二:允许循环引用此方案更像是绕过问题而非解决问题......