(没用)Spring01_spring的概述、IOC的引入

Spring

第1章 Spring 概述

1.1 spring

​ Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IOC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 SpringMVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架

1.2 Spring

  • 1997 年 IBM提出了EJB 的思想
  • 1998 年,SUN制定开发标准规范 EJB1.0
  • 1999 年,EJB1.1 发布
  • 2001 年,EJB2.0 发布
  • 2003 年,EJB2.1 发布
  • 2006 年,EJB3.0 发布
    • Rod Johnson ( spring 之父)
      Expert One-to-One J2EE Design and Development(2002)
      阐述了 J2EE 使用EJB 开发设计的优点及解决方案
      Expert One-to-One J2EE Development without EJB(2004)
      阐述了 J2EE 开发不使用 EJB的解决方式(Spring 雏形)
  • 2017 年 9 9 月份发布了 g spring 的最新版本 0 spring 5.0 通用版( GA )
    • spring是一个历史性的发展,这个版本有比较的大改动,与以往的spring有比较的大的改动

1.3 spring 的优势

  1. 方便解耦,简化开发
           通过 Spring提供的 IOC容器,可以将对象间的依赖关系交由 Spring进行控制,避免硬编码所造成的过度程序耦合。
           用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
  2. AOP 编程的支持
           通过 Spring的 AOP 功能,方便进行面向切面的编程,许多不容易用传统OOP 实现的功能可以通过 AOP 轻松应付。
  3. 声明式事务的支持
           可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量。
  4. 方便程序的测试
           可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可 做的事情。
  5. 方便集成各种优秀框架
            Spring可以降低各种框架的使用难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持。
  6. 低 降低 JavaEE API 的使用难度
           Spring对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的
    使用难度大为降低。
  7. Java 源码是经典学习范例
           Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以 及对 Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

1.4 spring 的体系结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QSNFsaqk-1606630795667)(D:\Desktop\截图\Spring的体系结构_看图王.jpg)]

无论持久层的数据库还是事务、AOP及消息机制、web相关的内容、test单元测试这些都离不开核心容器IOC的支持(都需要导入IOC的包和dtd依赖)

1.5 三层架构的spring位置

  • spring负责管理项目中的所有对象
  • 可以将Spring看做项目中对象的管家

在这里插入图片描述

1.6 Spring一站式框架

  • spring框架属于容器性质,容器中装什么对象就有什么功能,不仅不排斥其他框架,还能帮助其他框架管理对象
  • aop支持
  • ioc思想
  • spring jdbc
  • junit测试支持

1.7 Spring 环境的搭建

(1) 在普通的工程中:

  • ​ 要导的包(4+2)

  • 4个包(spring解压后libs)

    1. spring-beans-4.3.9.RELEASE.jar
    2. spring-context-4.3.9.RELEASE.jar
    3. spring-core-4.3.9.RELEASE.jar
    4. spring-expression-4.3.9.RELEASE.jar
  • 2个包日志包(整合包中)

    1. com.springsource.org.apache.commons.logging-1.1.1.jar
    2. com.springsource.org.apache.log4j-1.2.15.jar

(2) 在maven工程中:

  • ​ 导入相应的指标:

​ 在spring官网上,已经给出spring的开发包的坐标,也可以去下开发包

第二章 耦合和解耦以及IOC概念

2.1 什么是程序的耦合和解耦

  1. 耦合:程序间的依赖关系
    • 包含:
      • 类之间的依赖
      • 方法间的依赖
  2. 解耦:
    • 降低程序之间的依赖关系
    • 依赖关系不可能没有,只可能降低
    • 我们在开发中,有些依赖关系是必须的,有些依赖关系可以通过优化代码来解除的
    • 解耦的思路:
      1. 第一步:使用反射创建对象,而避免使用new关键字来创建对象
      2. 第二步:通过读取配置文件来获取要创建的对象的全限定类名
  3. 实际开发时应该做到哪些??
    • 编译时不依赖、运行时才依赖

2.2分析代码中存在的耦合度的问题

  • 各个包之间的关系
    在这里插入图片描述

  • 实体类(要保存到数据库中的实体类)

    (只是模拟一下,没有具体写)

    //实体类
    public class Account {
    }
    
  • 持久层

    • 持久层的接口

      //账户的持久层继承接口
      public interface IAccountDao {
         //模拟保存账户的操作
         void saveAccount(Account account);
      }
      
    • 持久成实现类

      //账户的持久层实现类
      public class AccountDaoImpl implements IAccountDao {
         public void saveAccount(Account account) {
            System.out.println("成功保存账户");
         }
      }
      
  • 业务层

    • 业务层接口

      //业务层的接口
      public interface IAccountService {
         //模拟保存Account账户
         void saveAccount(Account account);
      }
      
    • 业务层实现类

      //账户的业务成实现类:业务成接口的实现类
      public class AccountServiceImpl implements IAccountService {
         //在业务层new出持久成的的实现类,调用相应的方法
         //在这就出现了代码的耦合(应为是new出来的)
         private IAccountDao accountDao = new AccountDaoImpl();
         public void saveAccount(Account account) {
            accountDao.saveAccount(account);
         }
      }
      
  • 表现层

    //模拟一个表现层,用于调用业务层
    public class Client {
       public static void main(String[] args) {
           //在表现层是new出业务层的实体类,调用的相应的方法
           //在这就出现了代码的耦合(应为是new出来的)
          IAccountService iAccountService = new AccountServiceImpl();
          iAccountService.saveAccount(new Account());
       }
    }
    

我们可以发现在 业务层调用持久成 表现成调用业务层的时候 都使用的是new的方法来获取业务层和持久层的数据-------》这就体现了代码耦合

2.3怎么解决上面代码中的耦合问题—工厂模式解耦

  • 什么方式可以解决在使用业务层使用持久层、表现层使用业务层的时候不用new关键字???

  • 回顾一下解耦的步骤:

    • ​ 第一步:使用反射创建对象,而避免使用new关键字来创建对象
    • 第二步:通过读取配置文件来获取要创建的对象的全限定类名
  • 使用工厂模式解耦:

    • 创建Bean对象的工厂:
      
      Bean 在计算机英语里面,有可重用组件的含义(一个东西可以被多次的使用)
      javaBean:  用java语言编写的可重用组件
         JavaBean >  实体类
      
       他是干什么的?? 他就是创建我们service业务层和dao持久成对象的
       如何创建呢??
         第一步:需要一个配置文件来配置我们的service和dao
                  配置的内容: 唯一标志 = 全限定类名 (key=value的形式)
                         (使用xml文件或者properties文件)
         第二步:通过读取配置文件中的内容,反射创建service和dao的对象来使用
      

在这里插入图片描述

  • 配置文件:

    • 配置文件存放了,service实现类和Dao实现类的全限定类名

      accountService=com.zy.service.impl.AccountServiceImpl
      accountDao=com.zy.dao.Impl.AccountDaoImpl
      
  • javaBean工厂

    public class BeanFactory {
       //定义一个配置文件对象
       private static Properties properties;
       static {
          try {
             //实例化对象
             properties = new Properties();
             //好的properties文件的流对象
             InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
             properties.load(in);
          } catch (IOException e) {
             throw  new ExceptionInInitializerError("初始化bean.properties错误");
          }
       }
    
       public static  Object getBean(String beanName){
          Object bean = null;
          try {
             String beanPath = properties.getProperty(beanName);
             //通过传入的key键,得到配置文件中的全限定类名,通过newInstance方法创建对象
             bean = Class.forName(beanPath).newInstance();
          } catch (Exception e) {
             e.printStackTrace();
          }
          return bean;
       }
    }
    
  • 实体类(要保存到数据库中的实体类)

    (只是模拟一下,没有具体写)

    //实体类
    public class Account {
    }
    
  • 持久层

    • 持久层的接口

      //账户的持久层继承接口
      public interface IAccountDao {
         //模拟保存账户的操作
         void saveAccount(Account account);
      }
      
    • 持久成实现类

      //账户的持久层实现类
      public class AccountDaoImpl implements IAccountDao {
         public void saveAccount(Account account) {
            System.out.println("成功保存账户");
         }
      }
      
  • 业务层

    • 业务层接口

      //业务层的接口
      public interface IAccountService {
         //模拟保存Account账户
         void saveAccount(Account account);
      }
      
    • 业务层实现类

      //账户的业务成实现类:业务成接口的实现类
      public class AccountServiceImpl implements IAccountService {
         //在业务层new出持久成的的实现类,调用相应的方法
         //在这就出现了代码的耦合(应为是new出来的)
         //private IAccountDao accountDao = new AccountDaoImpl();
         //使用工厂创建持久层对象
         private IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao");
         public void saveAccount(Account account) {
            accountDao.saveAccount(account);
         }
      }
      
  • 表现层

    //模拟一个表现层,用于调用业务层
    public class Client {
       public static void main(String[] args) {
           //在表现层是new出业务层的实体类,调用的相应的方法
           //在这就出现了代码的耦合(应为是new出来的)
           //IAccountService iAccountService = new AccountServiceImpl();
           //使用工厂创建业务层对象
    	 IAccountService iAccountService = (IAccountService) BeanFactory.getBean("accountService");
          iAccountService.saveAccount(new Account());
       }
    }
    

2.4工厂模式解耦升级版

​分析上面的版本有什么缺陷??

​	 当多次在使用表现层调的时候:

​			要多次通过表现层多次访问业务层,业务层访问持久层,这之间多次的访问解析了配置文件,
			创建了多个对象,效率比较慢

​我们要实现什么,怎么进行优化??

​	多次的 表现层多次访问业务层,业务层访问持久层 使用同一个对象



​在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,
让一个类中的方法通过读取配置文件,把这些对象创建出来 并存起来。

在接下来的使用的时候,直接拿过来用就好了。
那么,这个读取配置文件,创建和获取三层对象的类就是工厂。
	public class BeanFactory {
   //定义一个配置文件对象
   private static Properties properties;
   //定义一个容器,放service和dao的实例化对象
   private static Map<String,Object> beanMap;
   static {
      try {
         //实例化对象
         properties = new Properties();
         //好的properties文件的流对象
         InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
         properties.load(in);
         //实例化容器
         beanMap = new HashMap<String,Object>();
         //枚举取出配置文件中的所有key
         Enumeration kets = properties.keys();
         //遍历枚举key得到value,创建对象放到beanMap中
         while (kets.hasMoreElements()) {
            try {
               //得到key键
               String key = kets.nextElement().toString();
               //得到配置文件中的全限定类名
               String beanpath = properties.getProperty(key);
               //反射创建对象
               Object value = Class.forName(beanpath).newInstance();
               //容器中放入相同的key键和创建好的对象
               beanMap.put(key, value);
            } catch (Exception e) {
               e.printStackTrace();
            }
         }

      } catch (IOException e) {
         throw  new ExceptionInInitializerError("初始化bean.properties错误");
      }
   }

   public static  Object getBean(String beanName){
//    Object bean = null;
//    try {
//       String beanPath = properties.getProperty(beanName);
//       bean = Class.forName(beanPath).newInstance();
//    } catch (Exception e) {
//       e.printStackTrace();
//    }
      //直接返回容器中的对象
      return beanMap.get(beanName);
   }
}

2.5 反转控制( IOC )的概念和作用

1 、对象存哪去?

  • 分析:
    • 由于我们是很多对象,肯定要找个集合来存。这时候有 Map 和 List 供选择。
    • 到底选 Map 还是 List 就看我们有没有查找需求。
    • 有查找需求,选 Map。所以我们的答案就是
    • 在应用加载时,创建一个 Map,用于存放三层对象。
      我们把这个 map 称之为 容器

2、还是没解释什么是工厂?

  • 工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。

  • 以前: 我们在获取对象时,都是采用 new 的方式。是主动的

在这里插入图片描述

  • 现在:我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。

在这里插入图片描述

3 为什么叫 反转控制 IOC ??

  • 为什么在使用工厂解耦时候,不叫降低依赖叫降低解耦呢??
    • 原来使用new的方法主动的创建一个对象,现在使用工厂的方式放到容器中实现解耦
    • 把创建对象的控制权利交给了框架

4 明确IOC的作用:

  • 削减计算机程序的耦合(降低我们代码中的依赖关系)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小镇男孩~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值